Home > OS >  How can I animate when rendering and unmount a component in React?
How can I animate when rendering and unmount a component in React?

Time:06-10

I trying animate a component when rendering and unmount it in React, but unsuccessfully.

Component to animate

One of the ways I've tried was create a state (fade) with the class of animation property, when rendering, the class is fadeIn and on will unmount the class is fadeOut

const handlePokemonDetails = async () => {

    if (pokemonDetails === true){
        setFade(styles.fadeOut)
        await timeout(500)
    }

    else{
        setFade(styles.fadeIn)
    }

    setPokemonDetails(!pokemonDetails)

}

...

<div className={pokemonDetails ? styles.pokemonDetails   " "   fade : ""}></div>

SASS code:

    .pokemonDetails
       position: absolute
       top: 0
       z-index: 3
       display: flex
       width: 35vmin
       height: 39.5vmin
       flex-direction: column
       background-color: rgba(210, 210, 210, 0.85)
       border-radius: 10px

    @keyframes fade
       0%
         height: 0vmin
       100%
         height: 39.5vmin

    .fadeIn
       animation: fade 0.5s normal
    
    .fadeOut
       animation: fade 0.5s reverse

But, when I change state to other class, the component don't apply this new class animation style. Does anyone know how I can fix this or another way to do it?

CodePudding user response:

Good question. I just finished writing hook for React that helps with that look at https://github.com/perymimon/React-Anime-Manager

Just publish ver2-alpha so the documentation is still lake.

import {useAnimeManager,ADDED,REMOVED} from "@perymimon/react-anime-manager"

 const phase2class = {
    [ADDED]: "fadeIn",
    [REMOVED]: "fadeOut",
}

function Pokemons({pokemones}){
    const pokemonesStates = useAnimeManager(pokemones);

    return (
        <pokemones>
            { pokemonesStates.map(state =>(
                <div className={phase2class[state.phase] } onAnimationEnd={state.done}/>
              )
            )}
        </pokemones>
    )
}

CodePudding user response:

This is the exact use case for react-transition-group.

Wrap your component inside <CSSTransition>

function App() {
  const [inProp, setInProp] = useState(false);
  return (
    <div>
      <CSSTransition in={inProp} timeout={200} classNames="my-node">
        <div>
          {"I'll receive my-node-* classes"}
        </div>
      </CSSTransition>
      <button type="button" onClick={() => setInProp(true)}>
        Click to Enter
      </button>
    </div>
  );
}

Then add CSS to your classes. If you set className of CSSTransition to my-node, you will have 4 classes to style:

.my-node-enter {
  opacity: 0;
}
.my-node-enter-active {
  opacity: 1;
  transition: opacity 200ms;
}
.my-node-exit {
  opacity: 1;
}
.my-node-exit-active {
  opacity: 0;
  transition: opacity 200ms;
}
  • Related