【问题标题】:React native - "Rendered more hooks than during the previous render?"React native - “渲染的钩子比之前的渲染更多?”
【发布时间】:2020-07-09 21:42:25
【问题描述】:

我只有在按照React native - "this.setState is not a function" trying to animate background color? 的建议合并了 useEffect() 挂钩后才遇到这个问题

通过以下,我得到

比上一次渲染时渲染了更多的钩子

export default props => {
      let [fontsLoaded] = useFonts({
        'Inter-SemiBoldItalic': 'https://rsms.me/inter/font-files/Inter-SemiBoldItalic.otf?v=3.12',
            'SequelSans-RomanDisp' : require('./assets/fonts/SequelSans-RomanDisp.ttf'),
            'SequelSans-BoldDisp' : require('./assets/fonts/SequelSans-BoldDisp.ttf'),
            'SequelSans-BlackDisp' : require('./assets/fonts/SequelSans-BlackDisp.ttf'),
      });
      if (!fontsLoaded) {
        return <AppLoading />;
      } else {
    
    //Set states
      const [backgroundColor, setBackgroundColor] = useState(new Animated.Value(0));

      useEffect(() => {
        setBackgroundColor(new Animated.Value(0));
      }, []);    // this will be only called on initial mounting of component,
      // so you can change this as your requirement maybe move this in a function which will be called,
      // you can't directly call setState/useState in render otherwise it will go in a infinite loop.
      useEffect(() => {
        Animated.timing(this.state.backgroundColor, {
          toValue: 100,
          duration: 5000
        }).start();
      }, [backgroundColor]);

      var color = this.state.colorValue.interpolate({
        inputRange: [0, 300],
        outputRange: ['rgba(255, 0, 0, 1)', 'rgba(0, 255, 0, 1)']
      });

    const styles = StyleSheet.create({
      container: { flex: 1,
      alignItems: 'center',
      justifyContent: 'center',
      backgroundColor: color
    },
      textWrapper: {
        height: hp('70%'), // 70% of height device screen
        width: wp('80%'),   // 80% of width device screen
        backgroundColor: '#fff',
        justifyContent: 'center',
        alignItems: 'center',
      },
      myText: {
        fontSize: hp('2%'), // End result looks like the provided UI mockup
        fontFamily: 'SequelSans-BoldDisp'
      }
    });

      return (
        <Animated.View style={styles.container}>
          <View style={styles.textWrapper}>
            <Text style={styles.myText}>Login</Text>
          </View>
        </Animated.View>
      );
  }
};

我只是想动画淡化视图的背景颜色。我尝试删除第一个 useEffect 以防它造成一些冗余,但这没有任何作用。我是 ReactNative 的新手 - 这里有什么问题?

编辑:

export default props => {
  let [fontsLoaded] = useFonts({
    'Inter-SemiBoldItalic': 'https://rsms.me/inter/font-files/Inter-SemiBoldItalic.otf?v=3.12',
        'SequelSans-RomanDisp' : require('./assets/fonts/SequelSans-RomanDisp.ttf'),
        'SequelSans-BoldDisp' : require('./assets/fonts/SequelSans-BoldDisp.ttf'),
        'SequelSans-BlackDisp' : require('./assets/fonts/SequelSans-BlackDisp.ttf'),
  });

  //Set states
    const [backgroundColor, setBackgroundColor] = useState(new Animated.Value(0));

    useEffect(() => {
      setBackgroundColor(new Animated.Value(0));
    }, []);    // this will be only called on initial mounting of component,
    // so you can change this as your requirement maybe move this in a function which will be called,
    // you can't directly call setState/useState in render otherwise it will go in a infinite loop.
    useEffect(() => {
      Animated.timing(useState(backgroundColor), {
        toValue: 100,
        duration: 7000
      }).start();
    }, [backgroundColor]);

    // var color = this.state.colorValue.interpolate({
    //   inputRange: [0, 300],
    //   outputRange: ['rgba(255, 0, 0, 1)', 'rgba(0, 255, 0, 1)']
    // });

//------------------------------------------------------------------->
  if (!fontsLoaded) {
    return <AppLoading />;
  } else {

    const styles = StyleSheet.create({
      container: { flex: 1,
      alignItems: 'center',
      justifyContent: 'center',
      backgroundColor: backgroundColor

新错误:

提供给“样式表”的无效属性“颜色”

动画 useNativeDriver 未指定

【问题讨论】:

  • 这是一个函数式组件,如果你想在这个组件中有状态,你必须使用 useState 钩子,并将所有 this.state 语句替换为 useState 变量。
  • 另外,您的 useState 声明不应在条件语句中移出。
  • @JatinderPalSingh 好的,请参阅上面的编辑。仍然出现错误

标签: javascript reactjs react-native


【解决方案1】:

在您的第一次渲染中(我猜)只有useFonts 钩子会在您返回&lt;AppLoading /&gt; 时被调用,因为!fontsLoaded。其余的钩子位于 else 块中,这意味着每次渲染时不会有相同数量的钩子。

查看https://reactjs.org/docs/hooks-rules.html 以获得更多解释,尤其是https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

【讨论】:

  • 好的,这是有道理的。我编辑了我的代码(见上文)以使用 useState 而不是 this.state,并将其全部移到 if else 之上。现在我收到错误 - “无效的钩子调用。只能在函数组件的主体内调用钩子”
  • 哦,我明白了,您在您的useEffect 之一中调用useState;我想你只需要backgroundColor 代替
  • 好的,只替换了 backgroundColor 并将颜色变量输入到我的样式表中,但这会导致各种错误。我不认为我这样做是正确的 - 你可以在你的答案中包含更多代码
  • 这也超出了最初问题的范围,但看起来您对Animated.timing() 的使用可能不正确,每个reactnative.dev/docs/animated#example 可能是useRef 对于Animated.value(0)
猜你喜欢
  • 2020-06-20
  • 2023-02-23
  • 1970-01-01
  • 2021-08-23
  • 2021-09-12
  • 2021-04-26
  • 2021-05-31
  • 2022-08-03
  • 2021-10-12
相关资源
最近更新 更多