首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在axios拦截器中使用UseNavigate的正确方法是什么?

在axios拦截器中使用UseNavigate的正确方法是什么?
EN

Stack Overflow用户
提问于 2022-10-16 09:04:45
回答 1查看 67关注 0票数 1

我已经为我的服务创建了一个axios拦截器,场景是如果特定的api调用失败。它将重定向到错误组件。但是它给了我错误的Error: Invalid hook call. Hooks can only be called inside of the body of a function component.

下面是我的agent.ts代码:

代码语言:javascript
复制
   axios.defaults.baseURL = "https://localhost:5001/api/";

const responseBody = (response: AxiosResponse) => response.data;

    axios.interceptors.response.use(
      (response) => {
        return response;
      },
      (error: AxiosError) => {
        const { data, status }: { data: any; status: any } = error.response!;
        const navigate = useNavigate();
        switch (status) {
          case 500:
            //toast.error(data.title);
            navigate("server-error");
            break;
          default:
            break;
        }
        return Promise.reject(error.response);
      }
    );

const request = {
  get: (url: string) => axios.get(url).then(responseBody),
};

const Catalog = {
  list: () => request.get("products"),
};

const agent = {
  Catalog,
};

在我的组件中,下面是调用请求的代码:

代码语言:javascript
复制
    useEffect(() => {
    agent.Catalog.list().then((products) => setProducts(products));
  }, []);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-10-16 11:59:04

正如错误中提到的,钩子只能在函数组件中使用。通过在非函数组件的函数中使用useNavigate,只会产生错误的结果。

您可以创建一个钩子来拦截请求,并在结果的拦截中使用useNavigate

下面的代码演示了如何在react组件中使用axios拦截器。

工作代码框示例:请注意,您需要在一个新窗口中打开web应用程序,而不是codesandox,因为我使用生活垃圾来模拟500状态代码请求。您可以访问非iframe版本的在这个链接中

导航到"Page“链接,它应该向响应500状态代码的URL发送请求。axios拦截器应该将页面引导回/路由。

代码语言:javascript
复制
// AxiosNavigation.js
import { useRef, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import axios from 'axios';

export function useAxiosNavigation() {
  // Use useRef to prevent a re-render in the useEffect.
  // A ref, cannot be used as a useEffect dependency, hence,
  // your linters shouldn't complain about missing dependencies.
  const navRef = useRef(useNavigate());

  useEffect(() => {
    const intercetpor = axios.interceptors.response.use(
      (response) => response,
      (error) => {
        switch (error?.response?.status) {
          case 500:
            navRef.current('/');
            break;
          default:
        }
        return Promise.reject(error);
      }
    );

    return () => {
      axios.interceptors.response.eject(intercetpor);
    };
  }, []);
}

export default function AxiosNavigation() {
  useAxiosNavigation();
  return <></>;
}

要使用上面的组件,我们需要在路由器中添加它,下面的例子使用MemoryRouter,但是如果您愿意,可以自由地将它更改为BrowserRouter

代码语言:javascript
复制
// App.js
import { MemoryRouter, Routes, Route, Link } from 'react-router-dom';
import AxiosNavigation from './AxiosNavigation';
import PageWithError from './Page-With-Error';

export default function App() {
  return (
    <main>
      <MemoryRouter>
        <AxiosNavigation />

        <header>
          <nav>
            <Link to="/">Home</Link>
            <Link to="/about">About</Link>
            <Link to="/page-with-error">Page with error</Link>
          </nav>
        </header>

        <article>
          <Routes>
            <Route path="/" element={<>Home Page</>} />
            <Route path="/about" element={<>About Page</>} />
            <Route path="/page-with-error" element={<PageWithError />} />
          </Routes>
        </article>
      </MemoryRouter>
    </main>
  );
}

还必须定义PageWithError组件,它只需向返回500状态代码的API发送一个请求。正如我们在上面实现的axios拦截器钩子中所描述的那样,它只是转到根页面/

代码语言:javascript
复制
// PageWithError.js
import axios from 'axios';
import { useState, useEffect } from 'react';

export default function PageWithError() {
  const [loading, setLoading] = useState(false);
  useEffect(() => {
    setLoading(true);
    axios
      .get('/api-500-error')
      .catch((error) => {
        console.log('caught', error.response);
      })
      .finally(() => {
        setLoading(false);
      });
  }, []);

  return <>Page With Error: {loading && 'going to home page...'}</>;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74085802

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档