Reanimated 2:更新状态会导致 animatedProps 中的动画重置,尽管没有更改共享值
Posted
技术标签:
【中文标题】Reanimated 2:更新状态会导致 animatedProps 中的动画重置,尽管没有更改共享值【英文标题】:Reanimated 2: Updating a state causes animation in animatedProps to reset despite not changing the shared value 【发布时间】:2021-09-15 13:55:02 【问题描述】:场景:我在屏幕上呈现了一个svg circle
和一个state
。我也有两个按钮。 Change Size
按钮将圆的大小(共享值)从 50 更改为 100 或从 100 更改为 50。更改状态按钮将状态从“苹果”更改为“橙色”或“橙色”更改为“苹果”。
[注意:动画不以任何方式使用状态。我还在每次重新渲染时控制台记录size.value
]
问题:一旦按下Change Size
按钮,它会将圆圈从50变为100。现在如果你按下Change State
按钮,它会改变状态,但它也会使虽然我们的日志显示共享值size.value
仍然是 100,但圆圈回到 50。
预期行为:预期圆的大小保持为 100,因为这是提供给圆的共享值。
代码:
import React, useState, useEffect from 'react';
import Text, View, Button from 'react-native';
import Animated,
useAnimatedProps,
useSharedValue,
withSpring,
from 'react-native-reanimated';
import Svg, Circle from 'react-native-svg';
const App = () =>
const [state, setState] = useState('apple');
const size = useSharedValue(50);
const animatedProps = useAnimatedProps(() =>
return
r: size.value / 2,
;
);
const AnimatedCircle = Animated.createAnimatedComponent(Circle);
useEffect(() =>
console.log('size.value =', size.value);
);
return (
<View style=flex: 1>
<Svg height=100 width=100>
<AnimatedCircle
cx="50"
cy="50"
fill="green"
animatedProps=animatedProps
/>
</Svg>
<Text>state</Text>
<Button
title="Change Size"
onPress=() =>
size.value = withSpring(size.value === 50 ? 100 : 50);
/>
<Button
title="Change State"
onPress=() =>
setState(state === 'apple' ? 'orange' : 'apple');
/>
</View>
);
export default App;
任何帮助将不胜感激????
【问题讨论】:
@UğurEren 就这么简单?非常感谢你,伙计。解决了。 【参考方案1】:只需将const AnimatedCircle = Animated.createAnimatedComponent(Circle);
移动到您的函数组件之外。因为,在每次渲染时,react 都会运行你的函数。由于 createAnimatedComponent 在你的函数体中,它也会重新运行,所以它会从头开始重新创建组件。但是您应该只创建一次组件。
import React, useState, useEffect from 'react';
import Text, View, Button from 'react-native';
import Animated,
useAnimatedProps,
useSharedValue,
withSpring,
from 'react-native-reanimated';
import Svg, Circle from 'react-native-svg';
const AnimatedCircle = Animated.createAnimatedComponent(Circle);
const App = () =>
const [state, setState] = useState('apple');
const size = useSharedValue(50);
const animatedProps = useAnimatedProps(() =>
return
r: size.value / 2,
;
);
useEffect(() =>
console.log('size.value =', size.value);
);
return (
<View style=flex: 1>
<Svg height=100 width=100>
<AnimatedCircle
cx="50"
cy="50"
fill="green"
animatedProps=animatedProps
/>
</Svg>
<Text>state</Text>
<Button
title="Change Size"
onPress=() =>
size.value = withSpring(size.value === 50 ? 100 : 50);
/>
<Button
title="Change State"
onPress=() =>
setState(state === 'apple' ? 'orange' : 'apple');
/>
</View>
);
【讨论】:
【参考方案2】:在状态更新时,功能组件被重新渲染,局部变量值被重新初始化。与其将 UI 组件(Circle)保留在不需要状态的父组件中,我们可以将其移动到不同的组件并用React.memo
包装。
React.memo 仅在更新 props 时重新渲染包装的组件。在这种情况下,当状态更新时,ui 组件中的道具将保持不变并且不会重新渲染。
让我们将圆形组件代码移动到新组件。
import React, useState, useEffect from 'react';
import Text, View, Button from 'react-native';
import Animated,
useAnimatedProps,
useSharedValue,
withSpring,
from 'react-native-reanimated';
import Svg, Circle from 'react-native-svg';
const App = () =>
const [state, setState] = useState('apple');
const size = useSharedValue(50);
useEffect(() =>
console.log('size.value =', size.value);
);
return (
<View style=flex: 1>
<Text>state</Text>
enter code here
enter code here
<CircleMemo size=size/>
<Button
title="Change Size"
onPress=() =>
size.value = withSpring(size.value === 50 ? 100 : 50);
/>
<Button
title="Change State"
onPress=() =>
setState(state === 'apple' ? 'orange' : 'apple');
/>
</View>
);
export default App;
现在用 React.memo 记忆 React 组件,这样它就不会在状态更新时重新渲染。
const CircleUI = (size)=>
const animatedProps = useAnimatedProps(() =>
return
r: size.value / 2,
;
);
const AnimatedCircle = Animated.createAnimatedComponent(Circle);
return (
<Svg height=100 width=100>
<AnimatedCircle
cx="50"
cy="50"
fill="green"
animatedProps=animatedProps
/>
</Svg>
)
const CircleMemo = React.memo(CircleUI);
【讨论】:
以上是关于Reanimated 2:更新状态会导致 animatedProps 中的动画重置,尽管没有更改共享值的主要内容,如果未能解决你的问题,请参考以下文章
react-native-reanimated iOS 崩溃
React Native Reanimated 2 为 SVG 路径的长度设置动画
安装 Reanimated 2 后仍会收到警告“如果您想使用 Reanimated 2 那么...”
React Native reanimated 不适用于插值