简体   繁体   English

如何使用 async/await 在 React 应用程序中中止 Axios 请求?

[英]How to abort Axios request in React apps using async/await?

Hi I created a React hook to handle Axios requests.嗨,我创建了一个 React 钩子来处理 Axios 请求。 The trouble I'm having is that I'm unable to successfully abort the request to prevent memory leak.我遇到的麻烦是我无法成功中止请求以防止内存泄漏。 When I switch between 2 pages that uses the hook, I get error:当我在使用钩子的 2 个页面之间切换时,出现错误:

Can't perform a React state update on an unmounted component.无法对未安装的组件执行 React 状态更新。 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.要解决此问题,请在 useEffect 清理函数中取消所有订阅和异步任务。

useAxios hook code:使用Axios挂钩代码:

import { useState, useEffect } from "react";
import axios from "axios";

const useAxios = (url, method = "GET") => {
  const [data, setData] = useState([]);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(false);
  const [body, setBody] = useState(null);

  useEffect(() => {
    const controller = new AbortController();

    const getData = async (body) => {
      setLoading(true);

      try {
        const res = body
          ? await axios.post(url, body, {
              signal: controller.signal,
            })
          : await axios.get(url, {
              signal: controller.signal,
            });
        setData(res.data);
        setError(null);
        setLoading(false);
      } catch (err) {
        console.log(err.message);
        setError(err.message);
        setLoading(false);
      }
    };

    if (method === "GET") {
      getData();
    } else if (method === "POST") {
      getData(body);
    }

    return () => {
      controller.abort();
    };
  }, [url, method, body]);

  return { data, error, loading, setBody };
};

export default useAxios;

Your setError and setLoading are both going to fire when aborting.您的setErrorsetLoading在中止时都会触发。

So you will want to set a flag in the unmount callback.因此,您需要在卸载回调中设置一个标志。 You can then conditionally call setError / setLoading based on this.然后,您可以基于此有条件地调用setError / setLoading

useEffect(() => {
  let aborting = false;
  try {
    ....
  } catch (err) {
    console.log(err.message);
    if (!aborting) {
        setError(err.message);
        setLoading(false);
    }
  } 
  ....
  return () => {
    aborting = true;
    controller.abort();
  }
}, ...

prevent memory leak防止内存泄漏

Just a note, this wound't actually be a memory leak, it's just a warning that it could have come from one.请注意,这个伤口实际上并不是内存泄漏,它只是一个警告,它可能来自一个人。 eg.例如。 using addEventListener without removeEventListener .使用addEventListener而不使用removeEventListener But in either case you would still want to prevent a setState on a umounted component.但在任何一种情况下,您仍然希望在已卸载的组件上阻止setState

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM