styled-component + react-transition-group = very simple Transition
Tags: javascript, react
Published: 2019-02-26 12:00:25

---
title: styled-component + react-transition-group = very simple Transition
published: true
description: 
tags: JavaScript, React
---

If we need animate react component, we can use library like [react-pose](https://popmotion.io/pose/) or [react-spring](https://www.react-spring.io/). Those library is very cool but so heavy if we need only tiny transition.

On the other hand, [react-transition-group](https://github.com/reactjs/react-transition-group) is so simple.

If we use `styled-componets`, `<Transition>` component may be better than `<CSSTransition>`

# Example

First, I create transition wrapped component.
In this example, I use React Hooks but you can use class component if you need.

```jsx
import { Transition } from "react-transition-group"
import { Animation } from "./Animation"

export const AnimateItem = () => {
  const [animate, setAnimate] = useState(false)

  // Animate on click button and revert after 3000ms.
  const doAnimate = useCallback(() => {
    setAnimate(true)
    setTimeout(() => {
      setAnimate(false)
    }, 3000)
  }, [])

  return (
    <div>
      {/* Transition change state with `in` props */}
      <Transition in={animate} timeout={500}>
        {(state) => (
          // state change: exited -> entering -> entered -> exiting -> exited
          <Animation state={state}>Hello</Animation>
        )}
      </Transition>
      <button onClick={doAnimate}>Animate</button>
    </div>
  )
}
```

Next, create component that based on styled-component.

```js
// Animation.js
import styled from "styled-components"

export const Animation = styled.div`
  transition: 0.5s;
  width: 300px;
  height: 200px;
  /* example for move item */
  transform: translateX(
    ${({ state }) => (state === "entering" || state === "entered" ? 400 : 0)}px
  );
  /* change color*/
  background: ${({ state }) => {
    switch (state) {
      case "entering":
        return "red"
      case "entered":
        return "blue"
      case "exiting":
        return "green"
      case "exited":
        return "yellow"
    }
  }};
`
```

You can split `Item` and `Animation` too.

```js
const BaseItem = styled.div`
  width: 300px;
  height: 200px;
`

export const Animation = styled(BaseItem)`
  transition: 0.5s;
  transform: translateX(
    ${({ state }) => (state === "entering" || state === "entered" ? 400 : 0)}px
  );
`
```

# Preview

![preview](https://thepracticaldev.s3.amazonaws.com/i/g6wm4fpwsvenaj24euji.gif)

# Fade example

You can create fadeIn/fadeOut animation with same way.

```jsx
export const Fade = styled.div`
  transition: 0.5s;
  opacity: ${({ state }) => (state === "entered" ? 1 : 0)};
  display: ${({ state }) => (state === "exited" ? "none" : "block")};
`
```

Or you can use with `unmountOnExit` and `mountOnEnter`.

```jsx

export const Fade2 = styled.div`
  transition: 5s;
  opacity: ${({ state }) => (state === "entered" ? 1 : 0)};
`

const Item = () => {
  // ...
  return <Transition in={animate} timeout={500} unmountOnExit mountOnEnter>
    {(state) => <Fade2 state={state}>Fade In</Fade2>}
  </Transition>
}

```