plus1tv / react-anime

✨ (ノ´ヮ´)ノ*:・゚✧ A super easy animation library for React!
https://codepen.io/collection/nrkjgo/
MIT License
1.56k stars 81 forks source link

Re-runs animation on every render #40

Open scarlac opened 6 years ago

scarlac commented 6 years ago

Trying to use react-anime for mounting/unmounting of components but animations are re-run every time component is re-rendered, regardless if something changes in child or <Anime ...> definition.

e.g. <Anime opacity={[0, 1]}>hello</Anime> will rapidly flash 'hello' each time you run setState or e.g. props are changed via Redux. This makes the library a bit useless, particularly for Redux, as component must manually be cached and wrapped to avoid this behaviour.

Maybe a feature to limit animations to only run when mounting/unmounting could fix it temporarily.

Version: 2.0.1

destefanis commented 6 years ago

Glad to see this issue reported, I just noticed the same thing. I wanted to animate a form into view. Which looks great! Well, until I start typing in the form and it changed the state. I'd love to use this library otherwise!

echoghi commented 6 years ago

I'm having the same issue with my form. I was able to get around it by setting the animation duration in state, then changing the duration to 0 in the complete prop. Now the animation appears in the initial render only, but the entire component disappears when my form submit handler fires...

echoghi commented 6 years ago

For the moment, I'm using a somewhat hacky workaround to render my form with the <Anime> wrapper on the initial render only, then replace it with the same form without the wrapper once the animation finishes. Its obviously not ideal, but it should serve to make your child component functional until this issue gets addressed.

ryanturnbullroam commented 6 years ago

@echoghni is there any source code you could provide for your workaround? Changing the props of my component the animation is placed in seems to force a re-render

danieljodeci commented 6 years ago

I seemed to stop my animation from "re-looping" by placing my Anime components isolated in their own PureComponent and setting up the shouldComponentUpdate lifecycle event to return false. This prevents my component from ever re-rendering after its' initial mount'

shouldComponentUpdate(nextProps, nextState){
    // Prevent Anime from rerendering animation
    return false;
}
davidrichard23 commented 6 years ago

@danieljodeci can you share how you did this? I isolated the component but the animation no longer works.

c0d3ster commented 4 years ago

I have created a workaround that solves the issue for my case of fading an element in only on the first render. If given the chance, I could make this more generic to support all opacity cases, set the ANIMATION_DURATION set to the duration prop value instead, and merge the fix into the library.

export const AnimeWrapper: React.FC = () => {
  const [startOpacity, setStartOpacity] = useState<number>(0)
  useEffect(() => {
    const delayOpacity = setTimeout(() => setStartOpacity(1), ANIMATION_DURATION)
    return () => clearTimeout(delayOpacity)
  }, [])

  return (
      <Anime
        duration={ANIMATION_DURATION}
        opacity={[startOpacity, 1]}
      >
        {children}
      </Anime>
  )
}