axios拦截器中的useContext

时间:2020-10-10 17:48:23

标签: reactjs axios use-context

我无法弄清楚为什么未在此函数中调用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组件中使用了相同的上下文。它在那里工作正常,只是不在这里运行!知道我在做什么错吗?

2 个答案:

答案 0 :(得分:1)

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

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

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

// WithAxios.js

import { useContext, useMemo } from 'react'
import axiosInstance from '../../axios'
import NotificationContext from '../Notification/NotificationContext'

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

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

    return children
}

export default WithAxios

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

// 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>
    )
}

答案 1 :(得分:0)

我在捕获此架构中的错误时没有任何问题。你在 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]);