[英]Implementing multiple Firestore calls at different times within useEffect React hook
[英]useEffect overriding the state instead of appending the values while making firestore calls
const [data, setData] = useState([])
const getDataFromFirebase = async () => {
let response = await firestore.collection('someDatabase').get()
response.forEach(item => setData([...data, item.data().name]))
}
useEffect(() => {
getDataFromFirebase()
},[])
data 被最新值覆盖,而不是将所有值添加到数组中。
在setData
中使用回调
setData(prevState => ([
...prevState, item.data().name
]));
原因是添加项目所花费的时间非常少,这就是为什么在反映之前,它被覆盖了。 您必须在 setData 中使用 prevState。 尝试这个:
const [data, setData] = useState([]) const getDataFromFirebase = async () => { let response = await firestore.collection('someDatabase').get() response.forEach(item => setData(prevState => ([...prevState, item.data().name]) ); } useEffect(() => { getDataFromFirebase() },[])
let response = await firestore.collection('someDatabase').get()
response.forEach(item => setData([...data, item.data().name]))
我不熟悉firestore
,但 promise 将被解决一次,你应该这样做:
const dataToAdd = response.map(item => item.data().name)
setData(prevState => ([...prevState, ...dataToAdd])
每次调用setData
时,您都会重新渲染组件,并且您不应该在同步循环中执行此操作。
prevState
在这里是必要的,因为您正在异步 function 中工作。 从理论上讲,如果您不在其他任何地方更改 state,则在使用带有dataToAdd
的解决方案后,它应该可以在没有它的情况下工作。
尝试此触发 setState 一次,但在此之前构建数组:
const [data, setData] = useState([])
const getDataFromFirebase = async () => {
let response = await firestore.collection('someDatabase').get()
const d = response.map(item=> item.data().name)
setData(d)
}
useEffect(() => {
getDataFromFirebase()
},[])
多次触发setData
会导致多次重新渲染,所以这里只触发一次。
在您下面的代码中,即使您稍后更改数据,数据的值也将始终为[]
。
const getDataFromFirebase = async () => {
let response = await firestore.collection('someDatabase').get()
response.forEach(item => setData([...data, item.data().name]))
}
这就是文档所说的
function 组件(称为 React 的渲染阶段)的主体中不允许发生突变、订阅、计时器、日志记录和其他副作用。 这样做会导致 UI 中出现令人困惑的错误和不一致。
在每个循环中调用 setData 并不是一个好主意。 一旦循环完成,填充一个数组并将其传递给setData
。
const getDataFromFirebase = async () => {
let response = await firestore.collection('someDatabase').get();
let newData = [];
response.forEach(item => newData.push(item.data().name));
// now set the new data
setData(prevData=> ([...prevData, ...newData]));
// or you can use Array.concat
// setData(prevData=> (prevData.concat(newData)));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.