Search code examples
reactjsreact-spring

React spring useTransition state updates modifying exiting component


I'm using react-spring to animate transitions in a list of text. My animation currently looks like this: enter image description here

As you can see, the text in the exiting component is also updating, when I would like it to stay the same.

Here's what I am trying:

import {useTransition, animated} from 'react-spring'
import React from 'react'

function useInterval(callback, delay) {
  const savedCallback = React.useRef();

  // Remember the latest callback.
  React.useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // Set up the interval.
  React.useEffect(() => {
    let id = setInterval(() => {
      savedCallback.current();
    }, delay);
    return () => clearInterval(id);
  }, [delay]);
}

function App() {
  const [copyIndex, setCopyIndex] = React.useState(0);
  const transitions = useTransition(copyIndex, null, {
    from: { opacity: 0, transform: 'translate3d(0,100%,0)', position: 'absolute'},
    enter: { opacity: 1, transform: 'translate3d(0,0,0)' },
    leave: { opacity: 0, transform: 'translate3d(0,-50%,0)' }
  });
  const copyList = ["hello", "world", "cats", "dogs"];

  useInterval(() => {
    setCopyIndex((copyIndex + 1) % copyList.length);
    console.log(`new copy index was ${copyIndex}`)
  }, 2000);
  return (
    transitions.map(({ item, props }) => (
      <animated.div style={props} key={item}>{copyList[copyIndex]}</animated.div>
    ))
  )
}

export default App;

Any ideas on how to get this to work as desired? Thank you so much!


Solution

  • Let the transition to manage your elements. Use the element instead of the index. Something like this:

    const transitions = useTransition(copyList[copyIndex], item => item, {
    

    ...

    transitions.map(({ item, props }) => (
      <animated.div style={props} key={item}>{item}</animated.div>
    ))