Search code examples
reactjsreact-hookstransitionreact-spring

items shuffled during transition-out of usetransitions


I'm trying to use the react-spring useTransition hook to toggle between an array of items and an extended version of the same array. The transition looks fine when expanding, but when transitioning back, the items get shuffled. Specifically, the last item in the old list moves to the first position while transitioning out. How can I prevent this from happening? I tried all combinations of the "reset" and "unique" options, modifying the original array instead of switching between two arrays, but nothing seems to help.

I found a similar issue at React-Spring useTransition shuffles my list items around but both the original and the "solution" sandbox are broken. Also just migrating to a newer version is not a solution for me.

Here is a working minimal example to show the problem : https://codesandbox.io/s/recursing-aryabhata-8u2ri


Solution

  • Your problem is very frustrating, because it should work and it is such a simple example. I could not figure an easy fix right now. It must something to do with the keys.

    But it works for me with the newer versions. If you change to 9.0.0-beta.1 for example.

    You can also try the newest 9.0.0-rc.3 version. I'm looking forward for the new 9 release. The transition is completely refactored.

    You can read about the changes here: https://aleclarson.github.io/react-spring/v9/#The-useTransition-rework

    Your example look like this with 9.0.0-rc.3:

    const itemsA = ["a", "b", "c"];
    const itemsB = ["d", "e", "f"];
    
    export default function App() {
      const [expanded, setExpanded] = useState(false);
      const items = expanded ? [...itemsA, ...itemsB] : [...itemsA];
      const transition = useTransition(items, {
        from: { opacity: 0, transform: "translate3d(100%,0,0)" },
        enter: { opacity: 1, transform: "translate3d(0%,0,0)" },
        leave: { opacity: 0, transform: "translate3d(50%,0,0)" },
        keys: p => p
      });
    
      return (
        <div className="simple-trans-main" onClick={() => setExpanded(!expanded)}>
          {transition((style, item, t, i) => (
            <animated.div style={style}>
              <h1>{item}</h1>
            </animated.div>
          ))}
        </div>
      );
    }
    

    https://codesandbox.io/s/basic-transition-with-v9-react-spring-ojp4w