【问题标题】:Cancel Axios request in useEffect not running在 useEffect 未运行时取消 Axios 请求
【发布时间】:2020-09-08 09:51:23
【问题描述】:

我正在尝试取消 axios 请求,但我只取得了部分成功。当我发出 GET 请求时,我有一个返回 Promise 的函数:

const getCards = (token) => {
  const URL = isDev
    ? "https://cors-anywhere.herokuapp.com/https://privacy.com/api/v1/card"
    : "https://privacy.com/api/v1/card";
  const config = {
    headers: {
      Authorization: `Bearer ${token}`,
    },
    cancelToken: source.token,
  };

  return axios.get(URL, config);
};

我在updateCards() 中调用这个函数,看起来像这样:

const updateCards = async () => {
  console.log("Updating Cards");

  setCards([]);
  setStarted(true);
  setLoading(true);

  let response = await getCards(token).catch((thrown) => {
    if (axios.isCancel(thrown)) {
      console.error("[UpdateCards]", thrown.message);
    }
  });

  /**
   * response is undefined when we cancel the request on unmount
   */

  if (typeof response === "undefined") return console.log("Undefined");

  console.log("Got Response from UpdateCards", response);

  setLoading(false);
};

我在 useEffect 钩子中取消我的请求:

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

我已经在我的状态声明下设置了我的 CancelToken,如下所示:

const CancelToken = axios.CancelToken;
const source = CancelToken.source();

我的问题是,如果我在 useEffect() 中调用我的 updateCards() 函数,我可以很好地取消它,但如果我使用按钮调用相同的函数,则不会运行取消。我到处寻找,我发现的唯一解决方案是我必须在 useEffect() 挂钩中调用我的请求,但这不是我想做的事情。我从这里去哪里?

以下是我看过的资源:

https://github.com/axios/axios#cancellation

https://medium.com/@selvaganesh93/how-to-clean-up-subscriptions-in-react-components-using-abortcontroller-72335f19b6f7

Cant cancel Axios post request via CancelToken

【问题讨论】:

  • 为什么不想使用useEffect 来更新卡片?
  • 因为用户可以随时发出另一个请求,这不一定是在组件挂载时。另外我想了解取消没有运行的原因。
  • source 中的useEffect 与发起请求的source 不同;该代码可能会取消与您预期不同的呼叫。你能粘贴source 被实例化的代码吗?您的问题听起来类似于Why am I seeing stale props or state inside my function?
  • 我自己其实也在想同样的事情,但不知道为什么会有所不同。这是我设置源的地方。让我把它上传到 hastebin。
  • hastebin.com/axemapahek.js @RossAllen 这是我的source 的设置位置。

标签: reactjs axios react-hooks


【解决方案1】:

要存储一个行为类似于组件的instance variable 的变量,您可以使用useRef。它是您想要的任何东西的容器。您可以将 CancelToken 存储在其中:

function Privacy(props) {
  const source = useRef(null);

  function getSource() {
    if (source.current == null) {
      const CancelToken = axios.CancelToken;
      source.current = CancelToken.source();
    }
    return source.current;
  }

  useEffect(() => {
    return () => {
      if (source.current != null) source.current.cancel();
    }
  }, [])

  // call `getSource()` wherever you need the Axios source
}

【讨论】:

  • 很有趣,我会看看 useRef 钩子,如果对我有用,我会更新帖子。谢谢!
  • 刚刚测试过,一切正常,感谢您的帮助。我最终按照您所说的做了,在发出 GET 请求时使用 getSource() 设置 cancelToken,然后使用 source.current 取消卸载时的请求。
  • 太好了,很高兴它成功了。 useRef 可以启用一些强大的 Hooks。您可以轻松地将这段代码拉入一个名为 useSource 或类似名称的新自定义钩子中,它会返回 source.current
猜你喜欢
  • 2019-12-19
  • 2017-10-14
  • 2021-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-11
  • 2020-03-31
相关资源
最近更新 更多