首页 > 解决方案 > 无法使用 useEffect 挂钩对未安装的组件执行 React 状态更新

问题描述

我有

useEffect(() => {
        setLoading(true);
        axios
            .get(url, {params})
            .then(data => {
                setData(data || []);
                setLoading(false);
            })
            .catch(() => {
                showToast('Load data failed!', 'error');
                setLoading(false);
            });

    }, [params]);

它给了我

警告:无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要解决此问题,请在 useEffect 清理函数中取消所有订阅和异步任务。

好的,问题不在于如何解决。当我在 promise 之后使用 setLoading(false)时,axios它工作正常,但在 promise 内部(例如上面)它总是给我警告。其实我想知道为什么会这样?有没有人可以简单地向我解释上面的代码流(上面的代码如何与警告一起工作的过程),并可能给出一些使用钩子的最佳实践。

标签: javascriptreactjsaxiosreact-hooksuse-effect

解决方案


你需要清理功能。这意味着您应该调用 useEffect 函数的函数结束。当依赖关系发生变化时(以参数为例)调用该函数。所以我们可以控制组件何时挂载/卸载

useEffect(() => {
  let cancelled = false;
  setLoading(false);
  async function fetchData() {
    try {
      const response = await axios.get(url, { params });
      if (!cancelled) {
        setData(response.data);
        setLoading(false);
      }
    } catch (e) {
      if (!cancelled) {
        showToast(e.message, "error");
        setLoading(false);
      }
    }
  }
  fetchData();
  // clean up here
  return () => {
    cancelled = true;
  };
}, [params]);

为什么会这样?

想象一下,您的请求变慢了,并且当异步请求完成时组件已经卸载。这次抛出这个警告


推荐阅读