如何摆脱 React Web 应用程序中的内存泄漏

How to get rid of memory leak in react web app

我的 ReactJS 网络应用程序中有这段代码:

useEffect(() => {
    const fetchInfo = async () => {
      const res = await fetch(`${api}&page=${page}`);
      setLoading(true);
      try {
        const x = await res.json();
        if (page === 1) {
          setItems(x);
          setAutoplay(true);
        } else {
          setItems({
            hasMore: x.hasMore,
            vacancies: [...items.vacancies, ...x.vacancies],
          });
        }
      } catch (err){
        console.log(err);
      }
      setLoading(false);
    };
    fetchInfo();
  }, [page]);

当此组件在 运行 异步函数卸载时,它会在控制台中抛出错误。

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

如何在清理中取消异步任务。

我在这里假设 setLoading 是在您的组件卸载后设置状态的函数,因此抛出此警告。如果是,那么你需要的是一个清理功能。

传递给useEffect的函数可以return一个函数,会在组件卸载之前调用(你可以认为它等同于旧的componentWillUnmount)-此处有更多详细信息:

https://reactjs.org/docs/hooks-effect.html#example-using-hooks

现在您可能需要某种标志来检查您调用 setLoading 是否安全,即将该标志默认设置为 true,然后将其设置为false 在 return 函数中。这是一篇应该有所帮助的好文章:

https://juliangaramendy.dev/use-promise-subscription/

现在我还没有测试过这个,但基本上你的代码看起来像这样:

useEffect(() => {
    const fetchInfo = async () => {
        let isSubscribed = true;
        const res = await fetch(`${api}&page=${page}`);
        if (isSubscribed) setLoading(true);
        try {
            const x = await res.json();
            if (page === 1) {
                setItems(x);
                setAutoplay(true);
            } else {
                setItems({
                    hasMore: x.hasMore,
                    vacancies: [...items.vacancies, ...x.vacancies]
                });
            }
        } catch (err) {
            console.log(err);
        }
        if (isSubscribed) setLoading(false);

        return () => (isSubscribed = false);
    };
    fetchInfo();
}, [page]);