Reactjs React Hook Useffect结合Firebase创建无限循环

Reactjs React Hook Useffect结合Firebase创建无限循环,reactjs,firebase,react-hooks,Reactjs,Firebase,React Hooks,我正在做一个使用Firebase和React挂钩的项目。在加载web应用程序之前,我希望通过运行如下所示的查询从Firebase获取所有数据 const [lists, setLists] = useState([]); useEffect(() => { const dataArray = []; /** handleWidgets */ listsRef .once('value', snap => { snap.forEach(function

我正在做一个使用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挂钩一起使用?现在,如果列表已更改或未更改,useEffect将始终运行。

已更新:

有几件事:

1) 您的
useffect
正在订阅此
useffect
中设置的
列表
,因此它将触发重新运行

2) 您正在尝试更新项目,然后重新获取包括更新项目在内的所有数据。你不需要这样做。一旦您从Firebase获得“初始状态”,所有修改都可能发生在状态中的列表上。是的,您将打电话进行添加/更新/删除,但您不需要每次都打电话获取全新的列表,因为您知道您更改了哪些信息,并且可以简单地更新状态列表以反映这一点,同时也可以打电话实际更新基础数据,以便当您离开Firebase时,您的列表会反映处于状态的列表

所以

从末尾的
[]
中删除
列表
,使您的代码只在装载时运行,如下所示:

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 []
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)
}
然后,让我们假设在add方法中,它看起来如下所示:

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 []
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)
}
等等,等等,从更新/删除方法开始。您只需使用该状态值,而无需调用Firebase以获取更新列表,因为您已经拥有该列表。

更新:

有几件事:

1) 您的
useffect
正在订阅此
useffect
中设置的
列表
,因此它将触发重新运行

2) 您正在尝试更新项目,然后重新获取包括更新项目在内的所有数据。你不需要这样做。一旦您从Firebase获得“初始状态”,所有修改都可能发生在状态中的列表上。是的,您将打电话进行添加/更新/删除,但您不需要每次都打电话获取全新的列表,因为您知道您更改了哪些信息,并且可以简单地更新状态列表以反映这一点,同时也可以打电话实际更新基础数据,以便当您离开Firebase时,您的列表会反映处于状态的列表

所以

从末尾的
[]
中删除
列表
,使您的代码只在装载时运行,如下所示:

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 []
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)
}
然后,让我们假设在add方法中,它看起来如下所示:

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 []
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)
}

等等,等等,从更新/删除方法开始。您将只使用该状态值,而不调用Firebase来获取更新列表,因为您已经拥有了它。

问题是,当用户插入新列表项或更改标题时,我想更新DOM。然后我想重新运行查询并从Firebase获取新数据。当用户更新列表值或插入新项时,是否也调用Firebase来更新基础数据?是的,它将获得新数据,但需要重新渲染dom我已更新我的答案-如果这仍然无法回答/解决您的问题,请告诉我。问题是,当用户插入新列表项或更改标题时,我想更新dom。然后,我想重新运行查询并从Firebase获取新数据。当用户更新列表值或插入新项时,是否也调用Firebase来更新基础数据?是的,它将获取新数据,但需要重新渲染dom。我已更新了我的答案-如果仍然无法回答/解决您的问题,请告诉我