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>;
});
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>;
});