React Native:渲染了比之前渲染错误更多的钩子

React Native: Rendered more hooks than during the previous render error

我在这个屏幕上的 React Native 应用程序中收到 Rendered more hooks than during the previous render 错误:

const HomeScreen = props => {
  const [refreshing, setRefreshing] = useState(false);

  if (props.data.loading) { // error shows its located here
    return <Text>Loading...</Text>; 
  }

  const onRefresh = useCallback(() => {
    setRefreshing(true);

    wait(2000).then(() => setRefreshing(false));
  }, [refreshing]);

  return (
    <View style={styles.container}>
      <FlatList
        data={props.data.sample}
        renderItem={({item}) => <Card {...item} user={props.data.user} />}
        keyExtractor={item => item._id}
        refreshControl={
          <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
        }
      />
    </View>
  );
};

但是当我将 useState 移动到 if 语句下方时:

const HomeScreen = props => {

  if (props.data.loading) { // error shows its located here
    return <Text>Loading...</Text>; 
  }

  // moved here, change in the order of hooks...
  const [refreshing, setRefreshing] = useState(false); 

  const onRefresh = useCallback(() => {
    setRefreshing(true);

    wait(2000).then(() => setRefreshing(false));
  }, [refreshing]);

我收到警告:

Warning: React has detected a change in the order of Hooks called by "HomeScreen". This will lead to bugs and errors if not fixed...

我的应用程序热重载时出现此错误,但是当我关闭警告然后强制重载时它不会出现。我只是想确保将它移到 if 语句下面是可以的。

另外,我不知道为什么移动useState会修复重新渲染的原始错误消息?

嗯,错误很明显。当 loading 为真时只调用 useState ,当它不为真时 useStateuseCallback 都会被调用,所以反应会抱怨钩子的数量不一致。该修复很可能是侥幸。这次当 loading 为真时没有钩子被调用,当它不是时它们都被渲染。 React 的源代码可能不会让 "number of hooks rendered" 检查该数字最初是否为零,因此没有错误。

正如警告告诉您的那样,有条件地调用挂钩(在任何挂钩之前编写 return 语句)不是一个好主意。在此特定情况下,它可能不会破坏您的应用程序,但总的来说这是一种不好的做法。钩子在每次渲染时都会被调用,React 需要正确地跟踪它们。

我会在条件 return 之前放置所有钩子(在本例中为 useStateuseCallback)。我看不出有什么理由不这样做。