繁体   English   中英

带有 useEffect 的无限循环 - ReactJS

[英]Infinite Loop with useEffect - ReactJS

我在使用 useEffect 钩子时遇到问题,它生成了一个无限循环。

我有一个在页面组装后立即加载的列表,并且在“开发人员”状态下发现新记录时也应该更新。

看代码:

  const [developers, setDevelopers] = useState<DevelopersData[]>([]);

  const getDevelopers = async () => {
    await api.get('/developers').then(response => {
      setDevelopers(response.data);
    });
  };
  
  // This way, the loop does not happen
  useEffect(() => {
    getDevelopers();
  }, []);

  // This way, infinte loop
  useEffect(() => {
    getDevelopers();
  }, [developers]);

  console.log(developers)

如果我删除开发人员对 useEffect 的第二个参数的依赖,则不会发生循环,但是,在找到新记录时不会更新列表。 如果我在 useEffect 的第二个参数中插入“developers”,列表会自动更新,但是,它会进入无限循环。

我究竟做错了什么?

完整代码(带组件): https : //gist.github.com/fredarend/c571d2b2fd88c734997a757bac6ab766

打印: 在此处输入图片说明

useEffect的依赖使用引用相等,而不是深度相等。 (如果出于某种原因需要进行深度相等比较,请查看use-deep-compare-effect 。)

API 调用总是返回一个新的数组对象,因此它的引用/标识与之前的不一样,触发useEffect再次触发效果等。

鉴于没有其他任何东西调用setDevelopers ,即developers无法更改,除非它来自效果触发的 API 调用,因此实际上没有实际需要让developers作为useEffect的依赖useEffect 你可以有一个空数组作为 deps: useEffect(() => ..., []) 该效果只会被调用一次。

编辑:在评论澄清之后,

我在左侧的表格中注册了一名开发人员 [...] 我希望在注册新开发人员后立即更新列表。

这是做事的一种方式:

这里的想法是developers只会在组件安装时自动加载。 当用户通过AddDeveloperForm添加新开发developers时,我们会在将新开发人员发布到后端的同时机会性地更新本地developers状态。 无论发布是否失败,我们都会从后端重新加载列表以确保我们拥有最新的真实状态。

const DevList: React.FC = () => {
  const [developers, setDevelopers] = useState<DevelopersData[]>([]);

  const getDevelopers = useCallback(async () => {
    await api.get("/developers").then((response) => {
      setDevelopers(response.data);
    });
  }, [setDevelopers]);

  useEffect(() => {
    getDevelopers();
  }, [getDevelopers]);

  const onAddDeveloper = useCallback(
    async (newDeveloper) => {
      const newDevelopers = developers.concat([newDeveloper]);
      setDevelopers(newDevelopers);
      try {
        await postNewDeveloperToAPI(newDeveloper); // TODO: Implement me
      } catch (e) {
        alert("Oops, failed posting developer information...");
      }
      getDevelopers();
    },
    [developers],
  );

  return (
    <>
      <AddDeveloperForm onAddDeveloper={onAddDeveloper} />
      <DeveloperList developers={developers} />
    </>
  );
};

问题是您的getDevelopers函数调用了setDevelopers函数,该函数更新了您的developers变量。 当您的developers变量更新时,它会触发useEffect函数

  useEffect(() => {
    getDevelopers();
  }, [developers]);

因为developers是传递给它的依赖项之一,并且该过程重新开始。

每次更新数组中作为 useEffect 的第二个参数的变量时,都会触发useEffect函数

在 useEffect 的第二个参数中使用空数组[] 这会导致内部代码仅在父组件的安装上运行。

useEffect(() => {
    getDevelopers();
  }, []);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM