更新状态时如何防止 react-spring 动画?

How to prevent react-spring animation when updating state?

当我更新动画元素的 属性 时,react-spring useTransition 动画出现问题。

我传递给 useTransition 的对象列表是:

const habits = [
  { id: "V3WV", name: "Go to gym", completions: [] },
  { id: "13t33", name: "Meditate", completions: [] },
  { id: "dghs4", name: "Practice guitar", completions: [] }
];

我的 useTransition 是:

const [habitsToShow, setHabitsToShow] = useState(habits);

const transitions = useTransition(habitsToShow, {
    from: {
      marginTop: -100,
      opacity: 0,
      transform: "translate3d(-150px,-40px,0)"
    },
    enter: {
      marginTop: 0,
      opacity: 1,
      transform: "translate3d(0px,0px,0)"
    },
    leave: {
      marginTop: 0,
      opacity: 0,
      transform: "translate3d(-150px,-40px,0)"
    },
    update: null
  });

我的“进入”和“离开”动画工作正常,但是当我尝试向状态对象的“完成”数组添加一个新的完成时:

const addCompletion = (habit) => {
    const indexOfHabit = habitsToShow.map((e) => e.id).indexOf(habit.id);

    // This doesn't mutate the state directly but causes re-render / "enter" of habit
    setHabitsToShow(
      habitsToShow.map((habit, i) =>
        i === indexOfHabit
          ? { ...habit, completions: [...habit.completions, 1] }
          : habit
      )
    );
  };

我尝试更新的对象被替换,“输入”动画运行,这不是所需的行为。期望的行为是没有动画发生,但“完成”计数器在 DOM 中的元素中得到更新。有人对此有解决方案吗?

这是一个代码框来说明行为: https://codesandbox.io/s/usetransition-react-spring-todo-jcikt

这是动画元素:

{transitions((props, item, state, index) => {
        return (
          <animated.div
            key={item.name}
            style={{
              ...props,
              border: "1px solid black",
              width: "70%",
              marginTop: "5px",
              marginBottom: "5px"
            }}
            className="box"
          >
            <div key={item.name}>
              <h1>{item.name}</h1>
              <h3>{`Completed: ${item.completions.length} times`}</h3>
              <div>
                <button onClick={() => handleRemove(index)}>Remove</button>
                <button onClick={() => addCompletion(item)}>Completed?</button>
              </div>
            </div>
          </animated.div>
        );
      })}

useTransition 使用引用相等性来区分其输入数组中的项目。如果您通过扩展语法创建一个新对象,那么就它而言,它是一个新项目。

您应该使用 keys 属性 来表示该项目是相同的:

const transitions = useTransition(habitsToShow, {
  keys: habit => habit.id,
  ...
});

更多信息请访问 react-spring docs