dmbaranov
dmbaranov

Reputation: 191

Animations with React

I have to create some complex animations. It was cool to develop them with jQuery or VanillaJS, but I guess that I should choose another way with React. Google gave me ReactCSSTransitionGroup but it seems to be broken and unmaintained (according to this message: github.com). E.g. I can't make a delay before starting the animation.

I also found a library called React-motion but I'm not sure if it's actually a tool that I need. So I want to ask whether you can recommend me something about it. Probably I should use VanillaJS (using refs and other ReactDOM functions)? Or there is another approach to it? Thanks in advance.

Upvotes: 2

Views: 3030

Answers (3)

Sergey Stadnik
Sergey Stadnik

Reputation: 3218

The easiest way to do animations in React, or, in fact, anywhere on the web, is to use CSS Transitions.

CSS Transitions actually has nothing to do with React. Quoting MDN,

CSS Transitions is a module of CSS that lets you create gradual transitions between the values of specific CSS properties. The behavior of these transitions can be controlled by specifying their timing function, duration, and other attributes.

Because CSS transitions is a pure CSS, they can be used in React applications, Angular, plain Javascript or even old-school server-rendered pages with no Javascript at all.

It is not the most versatile or powerful technique. But since in most cases the animations we want are pretty simple, why looking for something more complicated when a simple will do the job?

CSS Transitions are also well-supported by all major browsers with a notable exception of Opera Mini and IE below version 10.

CSS Transitions give us an ability to animate between the two CSS states. Let's say you want to animate opening and closing of a drawer (triggered by a click on a button). Let's assume we have a flex container around the drawer. When the drawer is opened, we want it to occupy 100% of the container width, therefore its max-width should be 100%. When it is closed, its width should be 0. We can create two CSS styles:

/* This CSS style is applied when the drawer is opened */
const openedStyle = {
  maxWidth: '100%' /* max-with is 100% when the drawer is opened */,
};

/* This CSS style is applied when the drawer is closed */
const closedStyle = {
  maxWidth: 0 /* max-width is 0 in the closed drawer */,
};

Then we handle opening / closing event apply one of those classes to the drawer object on opening / closing:

class Drawer extends React.Component {
  state = {
    opened: false // Initially search form is Closed
  };

  toggleOpened = () =>
    // Toggle opened / closed state.
    // Because we rely on the previous state, we need to use
    // a functional setState form
    // https://ozmoroz.com/2018/11/why-my-setstate-doesnt-work/
    this.setState(state => ({ ...state, opened: !state.opened }));

  render() {
    const { opened } = this.state;
    return (
      <div className="drawer-container col-12 col-md-4">
        <input
          type="text"
          className="drawer"
          // Apply 'openedStyle' CSS class if the drawer is opened,
          // and 'closedStyle' if the drawer is closed.
          style={opened ? openedStyle : closedStyle}
        />
        <button
          type="button"
          className="open-close-button btn btn-primary"
          onClick={this.toggleOpened}
        >
          {opened ? 'Close' : 'Open'}
        </button>
      </div>
    );
  }
}

export default Drawer;

When we press the "Open / Close" button, the drawer will flip between 0 and 100% width, effectively opening and closing.

Simple box toggle

All we need now is to animate it.

For that we need a secret ingredient - a CSS transition property. All we need to do is to add the following style to the drawer:

/* This CSS style is applied when the drawer is opened */
const openedStyle = {
  maxWidth: '100%' /* max-with is 100% when the drawer is opened */,
  /* Upon transitioning to Open,
     animate `max-width' for 0.5s*/
  transition: 'max-width 0.5s'
};

/* This CSS style is applied when the drawer is closed */
const closedStyle = {
  maxWidth: 0 /* max-width is 0 in the closed drawer */,
  /* Upon transitioning to Closed,
     animate `max-width' for 0.5s */
  transition: 'max-width 0.5s'
};

Voilà! We've got our animation - upon clicking the button our drawer is now expanded and collapsed within half a second!

Width transition

This is it in the nutshell, but there is more to it:

  • You can animate more than one CSS attribute with a CSS transition.
  • You can apply delay to transitionable properties, i.e. animate opacity first, and then animate width of the same element after 0.5 second delay.
  • You can apply various timing functions to transitions.

I wrote an expanded blog post explaining all the above: Painless React Animations via CSS Transitions.

Upvotes: 3

Harshal
Harshal

Reputation: 8308

Check out this easy to use and popular package:

https://www.npmjs.com/package/react-transition-group

Install:

npm install react-transition-group

Usage:

import { CSSTransition } from 'react-transition-group';

<CSSTransition
  in={toShow} // boolean value passed via state/props to either mount or unmount this component
  timeout={300}
  classNames='my-element' // IMP!
  unmountOnExit
>
  <ComponentToBeAnimated />
</CSSTransition>

NOTE: Make sure to apply below styles using the class property in CSS:

.my-element-enter {
  opacity: 0;
  transform: scale(0.9);
}
.my-element-enter-active {
  opacity: 1;
  transform: translateX(0);
  transition: opacity 300ms, transform 300ms;
}
.my-element-exit {
  opacity: 1;
}
.my-element-exit-active {
  opacity: 0;
  transform: scale(0.9);
  transition: opacity 300ms, transform 300ms;
}

Upvotes: 1

Tyran
Tyran

Reputation: 1

Maybe react-magic can help you.

Upvotes: 0

Related Questions