How to apply animation in React JS

Viewed 386

I'm using react-animated-css library to apply animations on state change in React JS.

The code is as follows:

import ReactDOM from "react-dom";
import React, { Component } from "react";
import { Animated } from "react-animated-css";

const animationIn = "fadeInLeft";
const animationOut = "fadeOutLeft";
const animationDuration = 400; // in ms

const arr = [
  {
    id: 1,
    name: "Test"
  },
  {
    id: 2,
    name: "Test1"
  },
  {
    id: 3,
    name: "Test3"
  },
  {
    id: 4,
    name: "Test4"
  },
  {
    id: 5,
    name: "Test5"
  }
];

class Selection extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selection: []
    };
    this.addSelection = this.addSelection.bind(this);
    this.removeItem = this.removeItem.bind(this);
  }

  addSelection(item) {
    const exists = this.state.selection.find(i => i.id === item.id);
    if (exists === undefined) {
      this.setState({ selection: [...this.state.selection, item] });
    }
  }

  removeItem(item) {
    this.setState({
      selection: this.state.selection.filter(i => i.id !== item.id)
    });
  }

  render() {
    return (
      <div
        style={{
          display: "flex",
          flexDirection: "row",
          justifyContent: "space-between"
        }}
      >
        <div>
          <h2>Choose from the list</h2>
          {arr.map(item => {
            return (
              <div
                key={item.id}
                style={{ marginBottom: 5, cursor: "pointer" }}
                onClick={() => this.addSelection(item)}
              >
                {item.name}
              </div>
            );
          })}
        </div>

        <div>
          <h1>Selection</h1>
          {this.state.selection.length < 1 ? (
            <div>Nothing selected</div>
          ) : (
            this.state.selection.map(l => {
              return (
                <Animated
                  key={l.name}
                  animationIn={animationIn}
                  animationOut={animationOut}
                  animationInDuration={animationDuration}
                  animationOutDuration={animationDuration}
                  isVisible={true}
                >
                  <div key={l.id} style={{ marginBottom: 5 }}>
                    {l.name}
                    <button
                      onClick={() => this.removeItem(l)}
                      style={{ marginLeft: 5, cursor: "pointer" }}
                    >
                      Remove
                    </button>
                  </div>
                </Animated>
              );
            })
          )}
        </div>
      </div>
    );
  }
}

ReactDOM.render(<Selection />, document.getElementById("root"));

It works fine when I click on some item on the left and add it to the state, but when I remove it it doesn't work.

Here is the example on sandbox.

Any idea how to apply the animation also on removing items from the state?

3 Answers

You need to play with the state of the props visible of your animation and add timeout.

addSelection(item) {
    const exists = this.state.selection.find(i => i.id === item.id);
    if (exists === undefined) {
      this.setState({
        selection: [...this.state.selection, item],
        [`visibleAnimate${item.id}`]: true
      });
    }
  }

  removeItem(item) {
    this.setState(
      {
        [`visibleAnimate${item.id}`]: false
        // selection: this.state.selection.filter(i => i.id !== item.id)
      },
      () => {
        setTimeout(() => {
          this.setState({
            selection: this.state.selection.filter(i => i.id !== item.id)
          });
        }, 300);
      }
    );
  }

Here the sandbox demo.

From a glance, it looks like you remove the animation with the item, which is why it doesn't play. Does it work if you wrap the animation around the whole selection list, starting below your h1?

You have to toggle the isVisible property to see the out animation. If the component is unmounted, it cannot be animated out.

Related