简体   繁体   English

与Firebase结合使用React Hook UseEffect创建无限循环

[英]React Hook UseEffect in combination with Firebase creating infinite loop

I'm working on a project that uses Firebase and React hooks. 我正在开发一个使用Firebase和React挂钩的项目。 Before the web application is loaded i want to get all the data from Firebase by running the query as shown below. 在加载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]);

For some reason the useEffect is always running and creating a huge performance issue. 由于某种原因,useEffect始终在运行,并造成了巨大的性能问题。 Is there a better way to use Firebase queries with React Hooks like useEffect? 是否有更好的方法将Firebase查询与诸如useEffect之类的React Hooks一起使用? Now if lists is changed or not the useEffect is always running. 现在,如果列表已更改,则useEffect始终在运行。

UPDATED: 更新:

A couple of things: 有两件事:

1) Your useEffect is subscribing to lists which is being set within this useEffect , so it's triggering a re-run. 1)您的useEffect订阅了在useEffect中设置的lists ,因此它触发了重新运行。

2) You're attempting to update the item and then re-fetch all of the data including the updated item. 2)您尝试更新项目,然后重新获取所有数据,包括更新的项目。 You don't need to do this. 您不需要这样做。 Once you have your "initial state" from Firebase, all of the modifications can happen to that list within state. 从Firebase获得“初始状态”后,状态中的该列表可能会发生所有修改。 Yes, you'll call to do the add/update/delete, but you don't need to call to get a brand new list each time because you know what information you've changed and can simply update your state list to reflect this while also calling to actually update the underlying data so that when you navigate away your list from Firebase reflects the list that was in state. 是的,您会打电话进行添加/更新/删除操作,但是您不必每次都打电话来获得一个全新的列表,因为您知道自己更改了哪些信息,并且只需更新状态列表即可反映出这一点。同时还调用以实际更新基础数据,以便当您从Firebase导航离开列表时,该列表会反映状态中的列表。

SO! 所以!

Remove the lists from the [] at the end so your code so it only runs on mount and looks like the following: []末尾删除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 []

Then, let's say in an add method, it would look something like the following: 然后,假设在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)
}

And so on and so forth from the update/delete methods. 等等,从更新/删除方法等等。 You're going to just use that state value without ever calling Firebase for an updated list because you already have it. 您将只使用该状态值,而无需调用Firebase获取更新列表,因为您已经拥有了它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM