Reanimated 2:更新状态会导致 animatedProps 中的动画重置,尽管没有更改共享值
Reanimated 2: Updating a state causes animation in animatedProps to reset despite not changing the shared value
场景:我在屏幕上呈现了一个 svg circle
和一个 state
。我也有两个按钮。 Change Size
按钮将圆的大小(共享值)从 50 更改为 100 或从 100 更改为 50。更改状态按钮将状态从 'apple' 更改为 'orange' 或 'orange' 为'apple'。
[注意:动画不以任何方式使用状态。我也在控制台记录 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;
任何帮助将不胜感激
只需将 const AnimatedCircle = Animated.createAnimatedComponent(Circle);
移动到您的功能组件之外。因为,在每个渲染反应上运行你的功能。由于 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>
);
}
在状态更新时,功能组件被重新渲染并且局部变量值被重新初始化。我们可以将它移动到不同的组件并用 React.memo
包装,而不是将 UI component(Circle) 保留在不需要直接状态的父级中。
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);
场景:我在屏幕上呈现了一个 svg circle
和一个 state
。我也有两个按钮。 Change Size
按钮将圆的大小(共享值)从 50 更改为 100 或从 100 更改为 50。更改状态按钮将状态从 'apple' 更改为 'orange' 或 'orange' 为'apple'。
[注意:动画不以任何方式使用状态。我也在控制台记录 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;
任何帮助将不胜感激
只需将 const AnimatedCircle = Animated.createAnimatedComponent(Circle);
移动到您的功能组件之外。因为,在每个渲染反应上运行你的功能。由于 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>
);
}
在状态更新时,功能组件被重新渲染并且局部变量值被重新初始化。我们可以将它移动到不同的组件并用 React.memo
包装,而不是将 UI component(Circle) 保留在不需要直接状态的父级中。
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);