0

场景:我在屏幕上渲染了一个svg circle和一个。state我也有两个按钮。Change Size按钮将圆圈的大小(共享值)从 50 更改为 100 或从 100 更改为 50。更改状态按钮将状态从“苹果”更改为“橙色”或“橙色”更改为“苹果”。[注意:动画不以任何方式使用状态。我也在控制台记录size.value每次重新渲染]

问题:一旦按下按钮,它会将Change Size圆圈的动画从 50 变为 100。现在,如果按下Change State按钮,它会改变状态,但也会使圆圈的大小回到 50,尽管我们的日志显示共享值size.value仍然是 100 .

预期行为:预期圆的大小保持 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;

任何帮助将非常感激

4

2 回答 2

3

只需将 移动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>
  );
}
于 2021-07-04T13:22:10.033 回答
0

在状态更新时,功能组件被重新渲染,局部变量值被重新初始化。与其将 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);
于 2021-08-30T19:35:51.007 回答