简体   繁体   English

在更改组件时使用 state 的反应原生钩子

[英]Use react native hooks for state in changing components

I'm building my first react native application and am having trouble fully understanding the newly introduced react hooks我正在构建我的第一个 react 本机应用程序,但无法完全理解新引入的 react 钩子

Based on the user using the app (and hence an API call), I have a number of PeopleListItem components per user.根据使用该应用程序的用户(以及因此的 API 调用),我每个用户都有许多PeopleListItem组件。 In each PeopleListItem I want to set a state, that changes based on the users actions in the app.在每个PeopleListItem中,我想设置一个 state,它会根据用户在应用程序中的操作而变化。 So user John doe could render a page with two PeopleListItem components as follows:因此,用户 John doe 可以呈现包含两个PeopleListItem组件的页面,如下所示:

<PeopleListItem>
   // Somewhere in the component definition
   const [attributeVale, setAttributeValue] = useState("Whatever")
</PeopleListItem>
<PeopleListItem>
   // Somewhere in the component definition
   const [attributeVale, setAttributeValue] = useState("Whatever")
</PeopleListItem>

This errors with:这与以下错误有关:

Error: Rendered more hooks than during the previous render.错误:渲染的钩子比上一次渲染时更多。

I'm a bit confused by this, as the number of PeopleListItem is static, it's just not known up front and hence a db call needs to be made.我对此有点困惑,因为PeopleListItem的数量是 static,只是事先不知道,因此需要进行 db 调用。 Theoretically though, I would want to change the number of PeopleListItem .但从理论上讲,我想更改PeopleListItem的数量。 Is it possible to use react native hooks for this use case?是否可以对这个用例使用反应原生钩子? If not, what would be the correct approach to use states in a variable number of components?如果不是,在可变数量的组件中使用状态的正确方法是什么?

export default function PeopleScreen() {
  const [snapshot, loading, _error] = useCollectionOnce(
    firebase.firestore().collection("people"),
  );

  if (loading) {
    return (
      <View style={styles.container}>
        <ActivityIndicator size="large" />
      </View>
    );
  }

  return (
    <View style={styles.container}>
      <ScrollView>
        {snapshot.docs.map((doc) => PeopleListItemComponent({ peopleDoc: doc }))}
      </ScrollView>
    </View>
  );
}


export function PeopleListItemComponent(props: PeopleListProps) {
  const [name, setName] = useState('Mary');

  }, []);
  useEffect(() => {
    console.log("Why isn't this working?");

  });
  return("")

When using hooks, you have to make sure that you call the same hooks in the same order on each render of a given component.使用钩子时,您必须确保在给定组件的每个渲染中以相同的顺序调用相同的钩子。 In other words, you have to follow The Rules of Hooks .换句话说,你必须遵守Hooks 的规则

The problem in your example is here:您的示例中的问题在这里:

<ScrollView>
    {snapshot.docs.map((doc) => PeopleListItemComponent({ peopleDoc: doc }))}
</ScrollView>

You are calling PeopleListItemComponent like a regular function.你调用PeopleListItemComponent就像一个普通的 function。 Since it contains hooks, you will get an error if you don't call PeopleListItemComponent the same number of times on each render.由于它包含钩子,因此如果您在每次渲染中调用PeopleListItemComponent的次数不同,您将收到错误消息。 It's just as if you called those hooks directly from within the map callback.就像您直接从map回调中调用这些钩子一样。

What you really want to do is render a React element for each item in docs .你真正想做的是为docs中的每个项目渲染一个 React 元素。 Make sure to give each element a unique key too.确保也给每个元素一个唯一的

<ScrollView>
    {snapshot.docs.map((doc) => (
        <PeopleListItemComponent
            key={doc.id}
            peopleDoc={doc}
        />
    ))}
</ScrollView>

It's perfectly OK to render components conditionally or within a loop, even if the component itself contains hooks.有条件地或在循环中渲染组件是完全可以的,即使组件本身包含钩子。 You just have to make sure to follow the Rules of Hooks within the body of each component.你只需要确保在每个组件的主体中都遵循 Hooks 规则。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM