当数据移动到单独的组件时重新渲染太多

too many re-renders when data moved to a separate component

目前,我正在使用此逻辑根据 grapqhl 查询的结果呈现数据。这很好用:

 const contacts = () => {
    const { loading, error, data } = useUsersQuery({
      variables: {
        where: { id: 1 },
      },
    });
    if (data) {
      console.log('DATA COMING', data);
      const contactName = data.users.nodes[0].userRelations[0].relatedUser.firstName
        .concat(' ')
        .concat(data.users.nodes[0].userRelations[0].relatedUser.lastName);
      return (
        <View style={styles.users}>
          <View style={styles.item} key={data.users.nodes[0].id}>
            <Thumbnail
              style={styles.thumbnail}
              source={{
                uri:
                  'https://cdn4.iconfinder.com/data/icons/avatars-xmas-giveaway/128/girl_avatar_child_kid-512.png',
              }}></Thumbnail>

            <Text style={styles.userName}>{contactName}</Text>
          </View>
        </View>
      );
    }
  };

  return (
    <SafeAreaView style={{ flex: 1 }}>
      <Container style={{ flex: 1, alignItems: 'center' }}>
        <Item style={styles.addToWhitelist}>
          <Icon name="add" onPress={() => navigation.navigate('AddContact')} />
          <Text style={styles.addToContactTitle}>Add contact</Text>
        </Item>
        <Text onPress={() => navigation.navigate('Home')}>Zurück</Text>
        <View style={{ width: moderateScale(350) }}>
          <Text>Keine Kontacte</Text>
        </View>
        {contacts()}
        {/* <ContactList data={userData}></ContactList> */}
      </Container>
    </SafeAreaView>
  );
};

但是,当我制作一个单独的组件时:

export const ContactList: React.FunctionComponent<UserProps> = ({
  data,
}) => {
  console.log('user called');
  if (!data) return null;
  console.log('DATA COMING', data);
      const contactName = data.users.nodes[0].userRelations[0].relatedUser.firstName
        .concat(' ')
        .concat(data.users.nodes[0].userRelations[0].relatedUser.lastName);
  return (
    <View style={styles.users}>
    <View style={styles.item} key={data.users.nodes[0].id}>
      <Thumbnail
        style={styles.thumbnail}
        source={{
          uri:
            'https://cdn4.iconfinder.com/data/icons/avatars-xmas-giveaway/128/girl_avatar_child_kid-512.png',
        }}></Thumbnail>
      <Text style={styles.userName}>{contactName}</Text>
    </View>
  </View>
  );
};

并这样称呼它:

 const [userData, setUserData] = useState<UsersQueryHookResult>('');

  const contacts = () => {
    console.log('running');
    const { loading, error, data } = useUsersQuery({
      variables: {
        where: { id: 1 },
      },
    });
    if (data) {
      setUserData(data);
    }
  };

  return (
    <SafeAreaView style={{ flex: 1 }}>
      <Container style={{ flex: 1, alignItems: 'center' }}>
        <Item style={styles.addToWhitelist}>
          <Icon name="add" onPress={() => navigation.navigate('AddContact')} />
          <Text style={styles.addToContactTitle}>Add contact</Text>
        </Item>
        <Text onPress={() => navigation.navigate('Home')}>Zurück</Text>
        <View style={{ width: moderateScale(350) }}>
          <Text>Keine Kontacte</Text>
        </View>
        {/* {contacts()} */}
        <ContactList data={userData}></ContactList>
      </Container>
    </SafeAreaView>
  );
};

但是,这给我带来了太多重新渲染的问题。我错过了什么?可能是一些基本的东西。我也尝试过使用 useEffects,但我无法在其中 运行 一个 graphql 查询挂钩。这给了我一个无效的钩子调用错误。

看来你的运行在无休止的递归中。

如果您在 render 块中调用 contacts 它会导致 setState(通过 setUserData)进行渲染,因此 contacts 被再次调用,依此类推直到无限(或直到错误)。