首页 > 解决方案 > 在 useEffect() 清理函数中卸载状态更新

问题描述

为了从 API 获取数据,我调用了一个 http 请求。有时我警告我一个错误,告诉我我正在尝试更新已卸载的状态。为了解决这个问题,我在 useEffect() 钩子中使用了清理功能,如下所示:

const [products, setProducts] = useState([]);

useEffect(() => {
    const source = axios.CancelToken.source();
    const token = source.token;

    const fetchProducts = async () => {
      try {
        const response = await ProductService.getProducts(token);
        setProducts(response.data);
      } catch (error) {
        console.log(error.message, error.response.status);
      }
    };

    fetchProducts();

    return () => {
      source.cancel();
    };
  }, []);

我的服务文件是这样的:

const ProductService = {
  getProducts: async function (token) {
    try {
      const response = await axios.get(myURL, {
        cancelToken: token

      });
      return response.data
    } catch (error) {
      throw error
    }
  }
};

在这种情况下我做了什么错误或不必要的事情,或者我可以更新这个代码块吗?请帮我。

标签: reactjsaxios

解决方案


我明白了,所以您处于异步请求成功之间的暮光区,因此取消令牌将不起作用,并且排队状态更新。

从这里你有几个选择。

  1. 忽略,因为这只是一个警告。您已经尝试过取消飞行中的网络请求,或取消订阅等......所以此时它只是一个警告。
  2. 使用旧的isMounted黑客。

使用isMountedhack 使用挂钩中的可变引用,该引用在useEffect卸载时将始终同步更新,并且可以在将状态更新入队之前作为最终检查。

useEffect(() => {
  const source = axios.CancelToken.source();
  const token = source.token;

  let isMounted = true;

  const fetchProducts = async () => {
    try {
      const response = await ProductService.getProducts(token);
      isMounted && setProducts(response.data);
    } catch (error) {
      console.log(error.message, error.response.status);
    }
  };

  fetchProducts();

  return () => {
    isMounted = false;
    source.cancel();
  };
}, []);

我称之为黑客,因为它实际上只是一种绕过/扼杀警告的方法。无论如何都会忽略对未安装组件的反应状态更新。


推荐阅读