反应:与自定义钩子无限循环问题相关联的useContext

时间:2020-10-02 13:41:26

标签: reactjs firebase react-hooks use-context

我正在创建与Google Firebase配对的待办事项应用程序,以存储我的数据。在应用程序中,您可以创建项目来组织任务。我正在使用useContext使我的应用程序可跨应用程序的所有组件进行访问。我的上下文在挂载时使用自定义钩子调用firebase来获取登录用户的项目(如果用户未在firebase中存储任何项目,则为空数组)。

我的问题是我的contextProvider进入了挂载循环,对firebase进行了新调用,以在每次挂载时设置项目(即使项目没有更改)。上下文实际上在我的应用程序中正常工作,我只意识到它正在循环,因为我一天之内就达到了可在freeplan上对firebase进行的最大调用。

这是我的上下文代码:

import React, { createContext, useContext } from "react";
import PropTypes from "prop-types";
import { useProjects } from "../Hooks/index";

export const ProjectsContext = createContext();
export const ProjectsProvider = ({ children }) => {
  const { projects, setProjects } = useProjects();

 
  return (
    <ProjectsContext.Provider value={{ projects, setProjects }}>
      {children}
    </ProjectsContext.Provider>
  );
};

export const useProjectsValue = () => useContext(ProjectsContext);

这是我的自定义钩子useProjects()的代码,该代码调用firebase来检索项目:

export const useProjects = () => {
  const [projects, setProjects] = useState([]);

  useEffect(() => {
    db.collection("projects")
      .where("userId", "==", "uBnTwu5ZfuPa5BE0xlkL")
      .orderBy("projectId")
      .get()
      .then((snapshot) => {
        const allProjects = snapshot.docs.map((project) => ({
          ...project.data(),
          docId: project.id,
        }));

        if (JSON.stringify(allProjects) !== JSON.stringify(projects)) {
          setProjects(allProjects);
        }
      });
  }, [projects]);

  return { projects, setProjects };
};

此外,我正在控制台中登录钩子,并在上下文中检查它被调用了多少次,这是一种好习惯还是有一种更好的方法来检查组件安装的次数?

预先感谢

1 个答案:

答案 0 :(得分:1)

您的代码陷入了循环,因为useEffect挂钩包含projects作为依赖项。随着useeffect中的代码更新projects,您的代码陷入无休止的状态更新和重新渲染周期。

查看您的代码,看来useEffectprojects语句中使用了if

if (JSON.stringify(allProjects) !== JSON.stringify(projects)) {
   setProjects(allProjects);
}

这似乎是您首先不应该做的事情。

如果您始终想接收实时更新,则可以observe projects集合,否则useEffect挂钩只能运行一次。

useEffect使用setProjects()函数,但是保证它不会改变,因此从useEffect钩子的依赖项数组中添加或省略它不会有什么区别。