Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animate when items in a list change order with React?

I have a list of items. When the order changes I want them to animate to their new position.

Before:

<ul>
  <li>One</li>
  <li>Two</li>
</ul>

After:

<ul>
  <li>Two</li>
  <li>One</li>
</ul>

Are there any libraries that can do this? Ive tired React Transition Group, React Pose and React Spring but none seem to support it, instead they focus on animations when items enter and leave the DOM. Im a bit surprised I haven't found anything as it seems like a common use case to me.

https://reactcommunity.org/react-transition-group/

https://popmotion.io/pose/

https://www.react-spring.io/

like image 954
Evanss Avatar asked Jun 26 '19 18:06

Evanss


People also ask

How to animate list reordering with react?

To animate list reordering with React, we can use the react-flip-move package. Then we add the FlipMove component and wrap it around the array of items we want to animate when reordering by writing: We have the Num component with a ref passed from App with forwardRef . Next, in App , we create the nums state with an array of items.

Can I animate items out of an array in react?

Animating items out of an array in React can be trickier than you’d think. If you have tried to roll your own solution yet, you have likely been frustrated by the fact that, once your state has been updated with an item removed, it’s gone (and hard to hold on to for the sake of animation!).

How to animate the exit of an item in react-transition-group?

By convention, react-transition-group will use the following styles: Since we’re currently only worried about animating the exit of an item from our list, we can actually get by with only using the .item-exit-active class: Here, we’re saying that, when the transition is active, set the opacity to 0 but with a 700ms ease-out transition.

How to sort items in listview using React and ionic react?

For React and Ionic React. React Listview item selection example. Select a single item or enable multiple selection for batch operations. For React and Ionic React. React Listview reorder demo. Grab and sort from drag handle on the left or right side, or tap/click and hold to sort. For React and Ionic React.


1 Answers

In react-spring there is an example about it. But it is quite complicated, there is a lot happening. I created a simplified version from it.

You have an array of names. You define a y value based on the index. And you can move the elements with translate property. The position is set to absolute.

With one click you can shuffle the array. With another click you can remove elements. In react transition, you can define the entering and leaving animation. The leaving animation called when you remove an element.

import { render } from 'react-dom';
import React, { useState } from 'react';
import { useTransition, animated } from 'react-spring';
import shuffle from 'lodash/shuffle';
import './styles.css';

let data = [
  {
    name: 'Rare Wind'
  },
  {
    name: 'Saint Petersburg'
  },
  {
    name: 'Deep Blue'
  },
  {
    name: 'Ripe Malinka'
  },
  {
    name: 'Near Moon'
  },
  {
    name: 'Wild Apple'
  }
];

function App() {
  const [rows, set] = useState(data);
  let height = 20;
  const transitions = useTransition(
    rows.map((data, i) => ({ ...data, height, y: i * height })),
    d => d.name,
    {
      from: { position: 'absolute', height: 20, opacity: 0 },
      leave: { height: 0, opacity: 0 },
      enter: ({ y, height }) => ({ y, height, opacity: 1 }),
      update: ({ y, height }) => ({ y, height })
    }
  );

  return (
    <div class="list" style={{ height }}>
      <button onClick={() => set(shuffle(rows))}>click</button>
      <button onClick={() => set(rows.slice(1))}>remove first</button>
      {transitions.map(({ item, props: { y, ...rest }, key }, index) => (
        <animated.div
          key={key}
          class="card"
          style={{
            zIndex: data.length - index,
            transform: y.interpolate(y => `translate3d(0,${y}px,0)`),
            ...rest
          }}
        >
          <div class="cell">
            <div class="details">{item.name}</div>
          </div>
        </animated.div>
      ))}
    </div>
  );
}

const rootElement = document.getElementById('root');
render(<App />, rootElement);

Here is the sandbox: https://codesandbox.io/s/animated-list-order-example-with-react-spring-teypu

Edit: I added add element as well, because it is a nicer example this way. :)

Update: This sandbox is from necrifede who updated my example to version 9.: https://codesandbox.io/s/animated-list-order-example-with-react-spring-forked-nhwqk9?file=/src/index.js

like image 53
Peter Ambruzs Avatar answered Nov 14 '22 21:11

Peter Ambruzs