LewisLA
LewisLA

Reputation: 33

React-Spring transition 'leave' animation not working

When spring items leave the DOM nothing (no leave animation) happens.

Full CodeSandbox: https://codesandbox.io/s/jzz6xv1y4w

const Todo = ({ todo, onDeleteClick }) => {
  const transition = useTransition(todo, null, {
    from: { opacity: 0, transform: "translateY(-10px)" },
    enter: { opacity: 1, transform: "translateY(0)" },
    leave: { opacity: 0, transform: "translateY(10px)" }
  });
  return transition.map(
    ({ item, props, key }) =>
      item && (
        <TodoContainer style={props} key={key}>
          <span>{todo}</span>
          <button onClick={onDeleteClick}>X</button>
        </TodoContainer>
      )
  );
};

Upvotes: 2

Views: 5812

Answers (2)

Peter Ambruzs
Peter Ambruzs

Reputation: 8223

Move your transition to the app component. The transition should handle all the todos. This way it could control the enter and leave events.

<div className="App">
  <h1>Todo App</h1>
  <input type="text" ref={ref} />
  <input type="submit" onClick={() => addTodo(ref.current.value)} />
  {/*  */}
  {transition.map(
    ({ item, props, key }, i) =>
      item && (
        <Todo
          transition={props}
          todo={item}
          onDeleteClick={() => deleteTodo(i)}
          key={key}
        />
      )
  )}
</div>

);

The Todo component will be more simple:

const Todo = ({ todo, onDeleteClick, transition }) => {
  return (
    <TodoContainer style={transition}>
      <span>{todo}</span>
      <button onClick={onDeleteClick}>X</button>
    </TodoContainer>
  );
};

Also make sure you provide an unique key for the transition. It helps to decide which component is entering and which is leaving. I used the todo text as the key in the example.

This is the example: https://codesandbox.io/s/goofy-chaplygin-whvt4

Upvotes: 3

Andrii Golubenko
Andrii Golubenko

Reputation: 5179

You have to render all your elements inside transition.map. Now you render them outside of transition.map by yourself, but wrap each element in transition.map. Your Todo elements are rendered and deleted here:

{todos.map((x, i) => (
    <Todo todo={x} onDeleteClick={() => deleteTodo(i)} key={x} />
))}

But they have to be rendered on and deleted here:

return transition.map(
    ({ item, props, key }) => (
        <TodoContainer style={props} key={key}>
          <span>{item}</span>
          <button onClick={onDeleteClick}>X</button>
        </TodoContainer>
      )
  );

You need to change your component Todo. It should render all items.

I create a working example for you: https://codesandbox.io/s/trusting-dewdney-jerxy

Upvotes: 0

Related Questions