【问题标题】:why custom hook , context with useEffect lead to infinite loop?为什么自定义钩子,带有useEffect的上下文会导致无限循环?
【发布时间】:2021-09-29 03:40:11
【问题描述】:

为什么这个简单的代码会导致 无限循环渲染 Projects 组件 及其子组件(自然而然)并且因为 useEffect 无限循环访问 firebase? 使用已导入 useProjects 自定义钩子的 contextProvider 管理状态。

自定义钩子:

export const useProjects = () => {
  const [projects, setProjects] = useState([]);
  useEffect(() => {
    const db = firebase
      .firestore()
      .collection("projects")
      .where("userId", "==", "1234567890")
      .orderBy("projectId")
      .get();
    db.then((result) => {
      const allProjects = result.docs.map((project) => ({
        docId: project.id,
        ...project.data(),
      }));

      if (JSON.stringify(allProjects) !== JSON.stringify(projects)) {
        setProjects(allProjects);
      }
    }).catch((err) => {
      console.log("useProjects error", err);
    });
  }, [projects]);
  return { projects, setProjects };
};

项目组件:

const Projects = () => {
  const [active, setActive] = useState(null);
  const { setSelectedProject } = useSelectedProjectValue();
  const { projects } = useProjectsValue();

  return (
    projects &&
    projects.map((project) => (
      <li
        key={Math.random()}
        className={
          active === project.projectId
            ? "sidebar__project active"
            : "sidebar__project"
        }
      >
        <div
          onClick={() => {
            setActive(project.projectId);
            setSelectedProject(project.projectId);
          }}
        >
          <IndividualProject
            className="individualProjectComp"
            project={project}
          />
        </div>
      </li>
    ))
  );
};

【问题讨论】:

    标签: javascript reactjs infinite-loop use-effect context-api


    【解决方案1】:

    您在 useEffect 中设置项目状态,它本身将项目作为依赖项,即使您在设置之前比较项目值,但在字符串化值时的一些更改会导致每次状态更新。

    您可以通过不将项目作为依赖项添加到 useEffect 来避免这种情况,因为 projects 仅在 useEffect 内部更新,而不会在其他任何地方更新

    export const useProjects = () => {
      const [projects, setProjects] = useState([]);
      useEffect(() => {
        const db = firebase
          .firestore()
          .collection("projects")
          .where("userId", "==", "1234567890")
          .orderBy("projectId")
          .get();
        db.then((result) => {
          const allProjects = result.docs.map((project) => ({
            docId: project.id,
            ...project.data(),
          }));
    
          setProjects(allProjects);
        }).catch((err) => {
          console.log("useProjects error", err);
        });
      }, []);
      return { projects, setProjects };
    };
    

    【讨论】:

    • tanx a lot ,它给我的警告是什么,我们最好不要使用空方括号作为第二个参数?
    • ESLint 警告会提示您,以防您缺少本应添加的依赖项。但是,如果您确定自己的操作是正确的,则可以使警告静音。查看此帖子了解更多详情:stackoverflow.com/questions/55840294/…
    猜你喜欢
    • 2021-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-11
    • 2020-02-26
    • 2021-12-09
    • 1970-01-01
    • 2020-10-27
    相关资源
    最近更新 更多