2

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>
      )
  );
};
LewisLA
  • 33
  • 1
  • 4

2 Answers2

3

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

Peter Ambruzs
  • 7,763
  • 3
  • 30
  • 36
0

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

Andrii Golubenko
  • 4,879
  • 1
  • 22
  • 27