如何在api.js中修改App.js的State?401时清除相关状态
解决axios拦截器401时清除App.js状态的问题
首先要修正你代码里的一个关键错误:你用了axios.interceptors.request.use(请求拦截器),但401是响应状态码,应该改用响应拦截器axios.interceptors.response.use,否则无法捕获到响应里的401状态。
下面是几种可行的解决方案:
方法1:给axios实例传入登出回调函数
通过在App.js中定义清除状态的函数,传递给api.js的axios实例,让拦截器可以直接调用这个函数。
修改api.js
/* api.js */ import axios from "axios"; const api = axios.create(); // 存储登出回调的变量 let logoutCallback = null; // 暴露设置回调的方法 export const setLogoutCallback = (callback) => { logoutCallback = callback; }; // 改用响应拦截器 api.interceptors.response.use( (response) => response, (error) => { // 加?.避免error.response为undefined的情况 if (error.response?.status === 401) { logoutCallback?.(); // 调用清除状态的回调 console.log("unauthenticated"); } return Promise.reject(error); } ); export default api;
修改App.js
/* App.js */ import { useState, useEffect } from "react"; import api, { setLogoutCallback } from "./api"; function App() { const [user, setUser] = useState(null); const [shifts, setShifts] = useState([]); const [jobs, setJobs] = useState([]); // 定义清除所有状态的登出函数 const handleLogout = () => { setUser(null); setShifts([]); setJobs([]); // 可选:清除localStorage/sessionStorage里的token等认证信息 }; useEffect(() => { // 将登出函数传给api.js setLogoutCallback(handleLogout); // 组件卸载时清空回调,避免内存泄漏 return () => setLogoutCallback(null); }, [handleLogout]); // 其他业务逻辑... return <div>你的组件内容</div>; } export default App;
方法2:使用React Context全局管理状态
如果项目中需要共享的状态较多,推荐用Context统一管理用户状态和登出逻辑,这样后续其他组件也能方便调用登出方法。
创建AuthContext.js
/* AuthContext.js */ import { createContext, useContext, useState } from "react"; const AuthContext = createContext(); export const AuthProvider = ({ children }) => { const [user, setUser] = useState(null); const [shifts, setShifts] = useState([]); const [jobs, setJobs] = useState([]); const logout = () => { setUser(null); setShifts([]); setJobs([]); // 可选:清除认证token }; return ( <AuthContext.Provider value={{ user, shifts, jobs, logout }}> {children} </AuthContext.Provider> ); }; // 自定义Hook,简化Context调用 export const useAuth = () => useContext(AuthContext);
修改api.js(复用方法1的回调逻辑)
/* api.js */ import axios from "axios"; const api = axios.create(); let logoutCallback = null; export const setLogoutCallback = (callback) => { logoutCallback = callback; }; api.interceptors.response.use( (response) => response, (error) => { if (error.response?.status === 401) { logoutCallback?.(); console.log("unauthenticated"); } return Promise.reject(error); } ); export default api;
修改App.js和入口文件
/* App.js */ import { useEffect } from "react"; import { useAuth } from "./AuthContext"; import api, { setLogoutCallback } from "./api"; function App() { const { logout } = useAuth(); useEffect(() => { setLogoutCallback(logout); return () => setLogoutCallback(null); }, [logout]); return <div>你的组件内容</div>; } export default App;
在入口文件index.js中用AuthProvider包裹App:
/* index.js */ import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App"; import { AuthProvider } from "./AuthContext"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <AuthProvider> <App /> </AuthProvider> );
方法3:使用自定义事件(适合简单场景)
在api.js中触发自定义事件,App.js监听该事件并执行清除状态操作。
修改api.js
/* api.js */ import axios from "axios"; const api = axios.create(); api.interceptors.response.use( (response) => response, (error) => { if (error.response?.status === 401) { // 触发自定义登出事件 window.dispatchEvent(new CustomEvent("userLogout")); console.log("unauthenticated"); } return Promise.reject(error); } ); export default api;
修改App.js
/* App.js */ import { useState, useEffect } from "react"; import api from "./api"; function App() { const [user, setUser] = useState(null); const [shifts, setShifts] = useState([]); const [jobs, setJobs] = useState([]); const handleLogout = () => { setUser(null); setShifts([]); setJobs([]); }; useEffect(() => { // 监听自定义事件 window.addEventListener("userLogout", handleLogout); // 组件卸载时移除监听 return () => window.removeEventListener("userLogout", handleLogout); }, []); return <div>你的组件内容</div>; } export default App;
内容的提问来源于stack exchange,提问作者Nicke7117
相关产品推荐
相关产品推荐

