hi是Firebase的新手,我想了解为什么该组件不断重渲染。 基本上我想要做的就是获取数据并显示它,并继续监听更改并更新数据,而无需重新加载页面
import React, { useState, useEffect } from 'react';
import firebase from '../util/firebase';
export default function Items() {
const [items, setItems] = useState();
useEffect(() => {
let data = [];
firebase
.firestore()
.collection('items')
.onSnapshot((snapshot) => {
let changes = snapshot.docChanges();
console.log(changes);
changes.forEach((change) => {
data.push(change.doc.data());
});
console.log(data);
});
setItems(data);
}, [items]);
return <div>{items && items.map((item) => <h1>{item.text}</h1>)}</div>;
}
答案 0 :(得分:1)
useEffect
在其中一个依赖项发生更改时重新运行传递给它的函数。
如果我们分析当前的useEffect
函数,您会看到它使用items
为setItems
设置了一个状态,这将导致重新渲染。但是依赖项还包含items
。
组件安装-> useEffect
->设置项目-> useEffect
检测到项目更改,重新运行->再次设置项目,然后继续。
由于您实际上并未在items
中使用useEffect
,因此可以安全地从依赖项数组中删除它。
这里的另一个危险是useSnapshot
函数是异步的,因此当编译器进入setItems
时,它将尚未运行useSnapshot
,因此数据将为空。要解决此问题,您可以在内部移动setItems
函数:
const [items, setItems] = useState();
useEffect(() => {
let data = [];
firebase
.firestore()
.collection("items")
.onSnapshot((snapshot) => {
let changes = snapshot.docChanges();
console.log(changes);
changes.forEach((change) => {
data.push(change.doc.data());
});
// spreading the data here did solve my problem
setItems([...data]);
});
}, []);