【问题标题】:Error using axios interceptors and responses使用 axios 拦截器和响应时出错
【发布时间】:2021-10-19 19:43:23
【问题描述】:

我正在使用“axios”:“^0.23.0”,以及 ReactJs 和 Typescript。

我想拦截请求和响应并添加用户的令牌。

当我尝试使用请求拦截器时,我收到以下错误:

Object is possibly 'undefined'.  TS2532
(property) AxiosRequestConfig<any>.headers?: AxiosRequestHeaders | undefined

           (config) => {
             const user = getUserLocalStorage();
             config.headers.Authorization = user?.token;
             ^
             return config;
           },
           (error) => {

当我将 .Authorization 添加到时发生此错误

config.headers.Authorization = user?.token;

我应该怎么做才能修复这个错误?

这些是我正在使用的方法:

api.ts

import axios from "axios";
import { getUserLocalStorage } from "../context/AuthProvider/util";

export const Api = axios.create({
  baseURL: "http://localhost:8000/",
});

Api.interceptors.request.use(
  (config) => {
    const user = getUserLocalStorage();
    config.headers.Authorization = user?.token;
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
)

util.ts

import { Api } from "../../services/api";
import { IUser } from "./types";

export function setUserLocalStorage (user: IUser | null) {
  localStorage.setItem('u', JSON.stringify(user));
}

export function getUserLocalStorage () {
  const json = localStorage.getItem('u');

  if (!json) {
    return null;
  }

  const user = JSON.parse(json);

  return user ?? null;
}

export async function LoginRequest (username: string, password: string) {
  try {
    const request = await Api.post(
      'login/', 
      {username, password}
    );
    return request.data;

  } catch (error) {
    return null;
  }
}

index.tsx

import React, {createContext, useEffect, useState} from "react";
import { IAuthProvider, IContext, IUser } from "./types";
import { getUserLocalStorage, LoginRequest, setUserLocalStorage } from "./util";

export const AuthContext = createContext<IContext>({} as IContext)

export const AuthProvider = ({children}: IAuthProvider) => {
  const [user, setUser] = useState<IUser | null>()

  useEffect(() => {
    const user = getUserLocalStorage();

    if (user) {
      setUser(user);
    }
  }, [])

  async function authenticate(
    username:string, 
    password: string
  ) {
    let response: any;
    response = await LoginRequest(username, password);
    const payload = {token: response.token};

    setUser(payload);
    setUserLocalStorage(payload);
  }

  function logout () {
    setUser(null);
    setUserLocalStorage(null);
  }

  return (
    <AuthContext.Provider value={{...user, authenticate, logout}}>
      {children}
    </AuthContext.Provider>
  )
}

谢谢!

【问题讨论】:

    标签: reactjs typescript axios request interceptor


    【解决方案1】:

    必须改变分配令牌值的方式。 变化:

    config.headers.Authorization = user?.token;
    
    

    为:

    config.headers = {
        Authorization: user?.token,
    };
    
    

    所以,它应该是这样的:

    export const Api = axios.create({
        baseURL: "http://localhost:8000/",
    });
    
    Api.interceptors.request.use(
        (config) => {
            const user = getUserLocalStorage();
    
            config.headers = {
                Authorization: user?.token,
            };
    
            return config;
        },
        (error) => {
            return Promise.reject(error);
        }
    );
    

    【讨论】:

      【解决方案2】:

      实际上,你不应该在拦截器上重新定义 headers 对象。

      相反,您应该在添加新的授权属性之前检查 headers 对象是否存在。

      所以,不要这样:

      Api.interceptors.request.use(
          (config) => {
              const user = getUserLocalStorage();
      
              // This might cause issues because the `headers` object is always being redefined here - previously passed headers will be discarded
              config.headers = {
                  Authorization: user?.token,
              };
      
              return config;
          },
          (error) => {
              return Promise.reject(error);
          }
      );
      

      你应该这样做:

      Api.interceptors.request.use(
          (config) => {
              const user = getUserLocalStorage();
      
              if(!config.headers) {
                  config.headers = {};
              }
      
              config.headers.Authorization = user?.token;
      
              return config;
          },
          (error) => {
              return Promise.reject(error);
          }
      );
      

      这样可以确保您不会忽略/覆盖可能来自axios.{post/get/delete/etc}(url, config) 调用的headers 对象。

      【讨论】:

        猜你喜欢
        • 2022-01-25
        • 2020-10-22
        • 2020-09-25
        • 2018-09-27
        • 2020-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多