Search code examples
reactjsreact-springreact-pose

react-spring equivalent of react-pose PoseGroup


React Pose PoseGroup simply animates elements of a list when the list change with the flipMove option

https://codesandbox.io/s/inspiring-herschel-37bvs

How to do it with react-spring?

{items.map(item => (
    <Item key={item} />
  ))}

I'd like to animate the list if an item is removed, and the animation smoothly fill the gap


Solution

  • Animating to position is a little more difficult in react-spring, as you have to manipulate the positions as styles. I like to use hook based animation so I converted the component to function. The best way to solve this problem is the useTransition function in react-spring. You can define from, enter and leave styles for it. And it will apply to each array item as they removed or added.

    For the position I need the y position first as data then as a property. So I map the index as y, and I introduce it to the props as a variable to interpolate from.

      const [items, setItems] = React.useState([0, 1, 2, 3]);
    
      const transitions = useTransition(
        items.map((item, i) => ({ label: item, y: i })),
        item => item.label,
        {
          from: { opacity: 0 },
          leave: { opacity: 0 },
          enter: ({ y }) => ({ y, opacity: 1 }),
          update: ({ y }) => ({ y })
        }
      );
    
    

    Then you can use the transition object in the render part to map the items with styles from it. The trick here is the transform style. The y now change based on the array order. We can create a nice transform style based on it to move the items around.

      <ul className="sidepanel">
        {transitions.map(({ item, props, key }, index) => (
          <animated.li
            style={{
              position: "absolute",
              opacity: props.opacity,
              transform: props.y.interpolate(
                y => `translate3d(0,${y * 40}px,0)`
              )
            }}
            className="item"
            data-key={item.label % 5}
            key={key}
            onClick={() => {
              setItems([0, 1, 3]);
            }}
          />
        ))}
      </ul>
    

    Finally the example, I added an add an shuffle button. https://codesandbox.io/s/react-spring-position-animation-di9rb