【问题标题】:useEffect dependency causing an infinite loopuseEffect 依赖导致无限循环
【发布时间】:2021-09-27 01:33:44
【问题描述】:

我正在创建一个连接到 Firebase 作为后端的简单议程应用程序。我想在每次写入时获取数据,并试图避开无限循环。

useEffect(() => {
    const getTodos = () => {
      console.log("I will run");
      db.collection("Users")
        .doc(user.email)
        .collection("Todos")
        .get()
        .then((snapshot) => {
          const loadedTodos = snapshot.docs.map((docs) => {
            return {
              todo: docs.data().todo,
              isCompleted: docs.data().isCompleted,
              id: docs.id,
            };
          });
          setTodos(loadedTodos ?? []);
        });
    };
    getTodos();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [todos]);

初始待办事项状态为空。但是,当我获取 firebase 数据时,它会发生变化,然后导致组件本身重新渲染,这会导致另一个获取再次导致无限循环。由于这个原因,我已经打破了firebase中火花计划的限制,并且因为临时阻塞而浪费了几天的工作。我认为这可以通过 useCallback 钩子解决,但我不知道如何。 此外,我想在聊天应用程序中添加相同的功能(数据将从两侧写入)。是否只有在两侧之一写入时才可以重新渲染,还是在这种情况下必须是无限循环?

【问题讨论】:

  • 这种行为是意料之中的,因为您在函数的依赖数组中保留了一个状态变量,并且在您尝试更新状态变量的函数内部。您是否尝试过将依赖项数组保留为空白,以便仅在组件安装时触发该函数?即,而不是 [todos] ,写 [ ]
  • 这使它只运行一次,我不希望这样,我希望它在每次用户使用添加待办事项的 addTodo 函数或 setCompletion 状态函数时运行。
  • @AhmadShaker - 显示更多代码。听起来你需要多次调用getTodos——用户登录时和待办事项更新时一次。您能否显示更多组件代码 - 特别是当待办事项更新时(setCompletion/addTodo)

标签: reactjs firebase


【解决方案1】:

你想要的效果依赖是user.email

useEffect(() => {
   const getTodos = () => {
     console.log("I will run");
     db.collection("Users")
       .doc(user.email)
       .collection("Todos")
       .get()
       .then((snapshot) => {
         const loadedTodos = snapshot.docs.map((docs) => {
           return {
             todo: docs.data().todo,
             isCompleted: docs.data().isCompleted,
             id: docs.id,
           };
         });
         setTodos(loadedTodos ?? []);
       });
   };
   getTodos();
 }, [user.email]);

您可以将其解读为:每次user.email 更改时,我都会想重新获取待办事项列表。

编辑:正如其他人所说,您观察到无限循环的原因是因为效果本身改变了效果的依赖关系,从而导致效果再次运行。这通常可以通过“提升状态”来解决 - 但在这种情况下,这是因为您使用了错误的依赖项。

【讨论】:

  • 如果用户已登录,则不应更改用户电子邮件,因此我认为这种方法不正确。
  • @AhmadShaker 仅仅因为用户电子邮件不应该更改并不意味着这不是正确的方法。 user.email 是此效果的依赖项。就是这样。
【解决方案2】:

我刚刚添加了一个新的 useState 钩子,shouldComponentRerender,它会在调用 (addTodos, deleteTodo, setCompletionState) 的函数时发生变化,然后添加 shouldComponentRerender 状态作为 useEffect 钩子的依赖项。给了我想要的结果。谢谢!

【讨论】:

    猜你喜欢
    • 2021-07-25
    • 2021-01-08
    • 2020-11-23
    • 2020-08-27
    • 2020-11-16
    相关资源
    最近更新 更多