Reactjs 从数据库获取数据时使用效果无限循环
在我的项目中,用于发送请求以获取我的用户数据并显示它们。我写了上面的代码,但我意识到如果我将“人”传递给useEffect的依赖项(第二个参数),react会向我的firebase发送无限请求,但是如果我删除并保持第二个参数为空,useEffect会正常工作,这两者之间的区别是什么 下面是进入无限循环的代码:Reactjs 从数据库获取数据时使用效果无限循环,reactjs,firebase,google-cloud-firestore,react-hooks,Reactjs,Firebase,Google Cloud Firestore,React Hooks,在我的项目中,用于发送请求以获取我的用户数据并显示它们。我写了上面的代码,但我意识到如果我将“人”传递给useEffect的依赖项(第二个参数),react会向我的firebase发送无限请求,但是如果我删除并保持第二个参数为空,useEffect会正常工作,这两者之间的区别是什么 下面是进入无限循环的代码: const [people, setPeople]=useState([]) useEffect(() => { const unsubscribe=database.co
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>
)
useEffect(() => {
... setPeople() ... // <- people changed
}, [people]); // <- run every time people changes
const[people,setPeople]=useState([])
useffect(()=>{
const unsubscribe=database.collection(“人”).onSnapshot(快照=>
setPeople(snapshot.docs.map(doc=>doc.data())
)
return()=>{
退订
}
},[people])//如果我用空列表更改第二个参数,这个问题就解决了。
返回(
火柴
{people.map(person=>
{person.name}
)}
)
问题
useffect
每次指定给依赖项数组的任何一个值发生更改时都会运行。因为,在db
呼叫之后,您正在更新您的人员。对数组people
的引用发生变化,从而触发useffect
解决方案
您不需要将人员放入依赖关系数组中。
您的useffect
功能不依赖于people
useEffect(() => {
const unsubscribe=database.collection("people").onSnapshot(snapshot=>
setPeople(snapshot.docs.map(doc=>doc.data()))
)
return () => {
unsubscribe()
}
}, [])
问题是在useEffect中设置状态后,people
值将被更改,这将触发另一个useEffect调用,从而产生无限循环
您可以将其修改为:-
useEffect(() => {
const unsubscribe=database.collection("people").onSnapshot(snapshot=>
setPeople(snapshot.docs.map(doc=>doc.data()))
)
return () => {
unsubscribe()
}
}, [])
本质上,每当依赖项数组(第二个参数)中的任何依赖项发生变化时,useffect
钩子都会运行内部函数代码
由于setPeople
会改变人,因此效果会在无限循环中运行:
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>
)
useEffect(() => {
... setPeople() ... // <- people changed
}, [people]); // <- run every time people changes
正如您正确指出的,只要去掉people
依赖项,就会告诉效果在组件“挂载”时只运行一次
另外,您可能想知道,如果您获取相同的精确结果,为什么人
会发生变化。这是因为比较很浅,每次创建数组时,它都是不同的对象:
const a=[1,2,3];
常数b=[1,2,3];
console.log(a==b);// 主要问题是,在每次set调用时创建的人员数组是不同的。对象完全不同。
我也有这个问题,因为我想显示的内容,一旦一些新的“人”被添加到数据库从管理面板,但事实证明,如果不刷新这件事不能解决,否则你可以做你自己的钩子与适当的比较
也许你可以通过比较人物数组的长度来尝试。我还没有尝试过,但我认为它会起作用。只需在那里使用一个空的依赖项数组作为[]
,这样它只会被触发一次。