将React Hook UseEffect与Firebase相结合,创建无限循环

时间:2019-05-13 11:53:13

标签: reactjs firebase react-hooks

我正在研究一个使用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始终在运行。

1 个答案:

答案 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获取更新列表,因为您已经拥有它。