从数据库获取数据时使用useEffect无限循环

时间:2020-10-06 13:17:48

标签: reactjs firebase google-cloud-firestore react-hooks

在我的项目中,用于发送获取我的用户数据并显示它们的请求。我写了上面的代码,但是我意识到,如果我将“ people”传递给useEffect的依赖项(第二个参数),react将无限请求发送到我的Firebase,但是如果我删除并保持第二个参数为空,useEffect可以正确解决这些区别两个?

这是进入无限循环的代码:

const [people, setPeople]=useState([])

useEffect(() => {
    const unsubscribe=database.collection("people").onSnapshot(snapshot=>
        setPeople(snapshot.docs.map(doc=>doc.data()))
        )
        

    return () => {
        unsubscribe()
    }
}, [people]) // if i change the second parameter with an empty list this problem solved.

return (
    <div>
        <h1>TinderCards</h1>
        <div className="tinderCards_cardContainer">
        {people.map(person =>
           <TinderCard
            className="swipe"
            key={person.name}
            preventSwipe={["up","down"]}
           >
            <div style={{backgroundImage: `url(${person.url})`}} className="card">
                <h3>{person.name}</h3>

            </div>
            </TinderCard> 
            )}
        </div>

    </div>
)

4 个答案:

答案 0 :(得分:1)

问题是在useEffect中设置状态后,people值将被更改,这将触发另一个useEffect调用,从而导致无限循环。

您可以对此进行修改:-

useEffect(() => {
    const unsubscribe=database.collection("people").onSnapshot(snapshot=>
        setPeople(snapshot.docs.map(doc=>doc.data()))
        )
        

    return () => {
        unsubscribe()
    }
}, [])

答案 1 :(得分:1)

实质上,每次依赖项数组(第二个参数)中的任何依赖项发生变化时,useEffect钩子都会运行内部函数代码。

由于setPeople会改变人们,因此效果会无限循环地运行:

useEffect(() => {
  ... setPeople() ... // <- people changed
}, [people]);         // <- run every time people changes

如果您需要某种方式的人的价值,并且需要将其放在依赖项数组中,则检查的一种方法是是否未定义people

useEffect(() => {
  if (!people) {
    // ... do something
    setPeople(something);
  }
}, [people]);

正如您正确指出的那样,当组件被“挂载”时,简单地去除people依赖关系就可以使效果只运行一次。

另外,您可能想知道为什么people会发生变化,如果要获取相同的准确结果。这是因为比较比较浅,并且每次创建数组时,它都是一个不同的对象:

const a = [1,2,3];
const b = [1,2,3];

console.log(a === b); // <- false

您需要为此进行深度相等性检查。

答案 2 :(得分:0)

问题

useEffect每当分配给依赖项数组的任何值更改时都运行。既然如此,您将在people调用之后更新db。对数组people的引用发生了变化,因此在useEffect上触发了无限循环

解决方案

您不需要将人员放入依赖项数组中。 您的useEffect函数不依赖于people

useEffect(() => {
    const unsubscribe=database.collection("people").onSnapshot(snapshot=>
        setPeople(snapshot.docs.map(doc=>doc.data()))
        )
        

    return () => {
        unsubscribe()
    }
}, [])

答案 3 :(得分:-1)

主要问题是在每次设置调用中创建的人员数组都不相同。对象是完全不同的。 我也遇到了麻烦,因为我想在管理面板中将一些新的“人员”添加到数据库后立即显示内容,但是事实证明,如果不刷新此内容就无法解决,否则您可以自己创建钩子进行适当的比较。

也许您可以通过比较PEOPLE数组的长度来尝试。我还没有尝试过,但是我认为它可以工作。