【问题标题】:useContext inside axios interceptoraxios拦截器中的useContext
【发布时间】:2023-04-06 19:04:01
【问题描述】:

我不明白为什么我的 useContext 没有在这个函数中被调用:

import { useContext } from "react";
import { MyContext } from "../contexts/MyContext.js";
import axios from "axios";

const baseURL = "...";

const axiosInstance = axios.create({
  baseURL: baseURL,
  timeout: 5000,
.
.
.
});
axiosInstance.interceptors.response.use(
  (response) => response,
  async (error) => {
    const { setUser } = useContext(MyContext);
    console.log("anything after this line is not running!!!!");
    setUser(null)

.
.
. 

我的目标是使用拦截器来检查令牌是否有效,以及它是否不清除用户并进行登录。我在其他反应组件中使用相同的上下文。它在那里工作正常,只是没有在这里运行!知道我做错了什么吗?

【问题讨论】:

  • 你没有导入 React 也没有 useContext
  • 哦,抱歉,忘记写那行了。它已经在文件中。尽管如此,仍然没有成功!

标签: reactjs axios use-context


【解决方案1】:

我和你有同样的问题。以下是我的解决方法:

你只能在功能组件中使用useContext,这就是为什么你不能在你的axios拦截器中执行setUser

您可以做的是创建一个名为 WithAxios 的单独文件:

// WithAxios.js

import { useContext, useMemo } from 'react'
import axios from 'axios'

const WithAxios = ({ children }) => {
    const { setUser } = useContext(MyContext);

    useMemo(() => {
        axios.interceptors.response.use(response => response, async (error) => {
            setUser(null)
        })
    }, [setUser])

    return children
}

export default WithAxios

然后在MyContext.Provider 之后添加WithAxios 以访问您的上下文,例如:

// App.js

const App = () => {
    const [user, setUser] = useState(initialState)

    return (
        <MyContext.Provider value={{ setUser }}>
            <WithAxios>
                {/* render the rest of your components here  */}
            </WithAxios>
        </MyContext.Provider>
    )
}

【讨论】:

  • 效果很好。感谢您的时间和信息。
  • 嗨,你将如何在这里访问错误对象,如果我尝试使用 error.response.status 它会给我未定义
  • 嘿马苏德。我在捕获此架构中的错误时没有任何问题。您是否在 axios 拦截器中捕获它们?这里我是如何修改它的:```
  • 我在使用拦截器文件中的上下文时遇到了麻烦,但使用了状态字符串属性(例如 access_token)。如果我尝试从我的上下文中获取 access_token,它总是为空的。使用上下文方法(signIn / signOut),我没有问题...有谁知道为什么?
【解决方案2】:

我在捕获此架构中的错误时没有任何问题。您是否在 axios 拦截器中捕获它们?这是我如何修改它的:

useMemo(() => {
    axiosInstance.interceptors.response.use(
      (response) => response,
      async (error) => {
        const originalRequest = error.config;

        // Prevent infinite loops
        if (
          error.response.status === 401 &&
          originalRequest.url === // your auth url ***
        ) {
          handleLogout();
          return Promise.reject(error);
        }

        if (
          error.response.status === 401 &&
          error.response.data.detail === "Token is invalid or expired"
        ) {
          handleLogout(); // a function to handle logout (house keeping ... ) 
          return Promise.reject(error);
        }
        if (
          error.response.data.code === "token_not_valid" &&
          error.response.status === 401 &&
          error.response.statusText === "Unauthorized"
        ) {
          const refreshToken = // get the refresh token from where you store

          if (refreshToken && refreshToken !== "undefined") {
            const tokenParts = JSON.parse(atob(refreshToken.split(".")[1]));

            // exp date in token is expressed in seconds, while now() returns milliseconds:
            const now = Math.ceil(Date.now() / 1000);

            if (tokenParts.exp > now) {
              try {
                const response = await axiosInstance.post(
                  "***your auth url****",
                  {
//your refresh parameters
                    refresh: refreshToken,
                  }
                );
                
// some internal stuff here ***

                return axiosInstance(originalRequest);
              } catch (err) {
                console.log(err);
                handleLogout();
              }
            } else {
              console.log("Refresh token is expired", tokenParts.exp, now);
              handleLogout();
            }
          } else {
            console.log("Refresh token not available.");
            handleLogout();
          }
        }

        // specific error handling done elsewhere
        return Promise.reject(error);
      }
    );
  }, [setUser]);

【讨论】:

  • 你能显示 axiosInstance 的代码吗?
猜你喜欢
  • 2019-03-27
  • 2018-11-27
  • 2022-11-09
  • 2020-01-19
  • 2019-06-26
  • 2021-05-10
  • 1970-01-01
  • 1970-01-01
  • 2018-01-20
相关资源
最近更新 更多