我正在研究一个使用Firebase和React钩子的项目。在加载Web应用程序之前,我想通过运行查询来从Firebase获取所有数据,如下所示。
const [lists, setLists] = useState([]);
useEffect(() => {
const dataArray = [];
/** handleWidgets */
listsRef
.once('value', snap => {
snap.forEach(function(result) {
firebase
.database()
.ref('lists')
.child(result.key)
.on('value', snap => {
if (snap.val()) dataArray.push(snap.val());
});
});
})
.then(function() {
setLists(dataArray);
});
}, [lists]);
由于某种原因,useEffect始终在运行,并导致巨大的性能问题。是否有更好的方法将Firebase查询与诸如useEffect之类的React Hooks一起使用?现在,无论列表是否更改,useEffect始终在运行。
答案 0 :(得分:0)
已更新:
几件事:
1)您的useEffect
订阅了lists
中设置的useEffect
,因此触发了重新运行。
2)您正在尝试更新项目,然后重新获取所有数据,包括更新后的项目。您不需要这样做。从Firebase获得“初始状态”后,状态中的该列表可能会发生所有修改。是的,您会打电话进行添加/更新/删除操作,但是您不必每次都打电话来获得一个全新的列表,因为您知道自己更改了哪些信息,并且只需更新状态列表即可反映出这一点。同时还调用实际更新基础数据,以便当您从Firebase导航离开列表时,会反映出状态中的列表。
所以!
最后从lists
中删除[]
,使您的代码仅在安装时运行,如下所示:
const [lists, setLists] = useState([]);
useEffect(() => {
const dataArray = [];
/** handleWidgets */
listsRef
.once('value', snap => {
snap.forEach(function(result) {
firebase
.database()
.ref('lists')
.child(result.key)
.once('value', snap => {
if (snap.val()) dataArray.push(snap.val());
});
});
})
.then(function() {
setLists(dataArray);
});
}, []); // removed lists from subscription []
然后,在add方法中,它看起来类似于以下内容:
addItem = listItem => {
// make copy of array in state
const newLists = [...lists];
// add item to list
newLists.push(listItem);
// update list in DB with firebase
/* firebase call here with new list item */
// update state lists with new array that has new item
setLists(newLists)
}
等等,来自update / delete方法。您将只使用该状态值,而不必调用Firebase获取更新列表,因为您已经拥有它。