react-spring@next - 具有异步功能的 spring 作为 'to' 为每个渲染设置动画

react-spring@next - a spring with async func as 'to' animating every render

A react-spring(版本 9)spring 其 'to' 值是一个异步函数,每次重新渲染都会经历其动画循环。如果 'to' 是普通对象,则动画仅在最初触发,如预期的那样。

考虑这个组件:

const Component = () => {
    // let's trigger some rerenders
    const [state, setState] = useState(false);
    useEffect(() => {
        setInterval(() => {
            setState(x => !x);
        }, 1000);
    }, []);

    // a spring with an async func provided to 'to'
    const props = useSpring({
        to: async (next, cancel) => {
            await next({opacity: 1, color: '#ffaaee'})
            await next({opacity: 0, color: 'rgb(14,26,19)'})
        },
        from: {opacity: 0, color: 'red'}
    });

    return <animated.div style={props}>I will fade in and out</animated.div>
};

文字会一直闪烁。

我认为这不是预期的行为。这是一个错误,还是我做错了什么?

我认为预期的行为是显示 useSpring 的 属性 的当前状态。当它是常量时,它将始终在每次渲染时显示相同的状态。但是你可以把usespring的改成属性。例如:

const ComponentColor = () => {
  const [color, setColor] = React.useState("red");

  const props = useSpring({
    to: { color },
    from: { color: "red" }
  });

  return (
    <>
      <animated.h2 style={props}>This color will change</animated.h2>
      <button onClick={() => setColor("blue")}>blue</button>
      <button onClick={() => setColor("green")}>green</button>
      <button onClick={() => setColor("orange")}>orange</button>
    </>
  );
};

在这种情况下,文本的颜色将变为您按下的颜色。我认为你的例子符合这个。在每次渲染时,它将显示 to 属性 的当前状态,这是一个序列。所以我认为这是预期的行为。

如果您希望 useState 仅在第一次渲染时设置动画。然后,您可以将动画部分重构为一个新组件,并确保它只会在第一次渲染时呈现。例如,如果您使用 React.memo,只有当其中一个属性发生变化时,它才会重新渲染您的函数组件。在这个例子中没有 属性 所以它只会在第一次呈现。

const Component = () => {
  // let's trigger some rerenders
  const [state, setState] = React.useState(false);
  React.useEffect(() => {
    setInterval(() => {
      setState(x => !x);
    }, 2000);
  }, []);

  return <FirstTimeAnimate />;
};

const FirstTimeAnimate = React.memo(() => {
  const props = useSpring({
    to: async (next, cancel) => {
      await next({ opacity: 0.25, color: "#black" });
      await next({ opacity: 1, color: "blue" });
    },
    from: { opacity: 0, color: "red" }
  });

  return <animated.h2 style={props}>I will fade in and out</animated.h2>;
});

https://codesandbox.io/s/fervent-margulis-drt5l