首页 > 解决方案 > 如何摆脱 React Web 应用程序中的内存泄漏

问题描述

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

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.

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

标签: javascriptreactjsmemory-leaks

解决方案


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

传递给的函数useEffect可以返回一个函数,该函数将在组件卸载之前调用(您可以将其视为 old 的等价物componentWillUnmount) - 更多细节在这里:

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

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

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]);

推荐阅读