无法使用useEffect钩子对未安装的组件执行React状态更新

时间:2020-04-07 10:42:07

标签: javascript reactjs axios react-hooks use-effect

我有

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

    }, [params]);

它给了我

警告:无法在已卸载的组件上执行React状态更新。这是空操作,但它表明应用程序中发生内存泄漏。要修复,请取消使用useEffect清理功能中的所有订阅和异步任务。

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

1 个答案:

答案 0 :(得分:2)

您需要清理功能。 这意味着您应该在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]);

为什么会这样?

想象一下,您的请求速度很慢,并且异步请求完成时组件已经卸载。这次发出警告