React组件挂载时API请求报403错误,刷新页面后恢复正常
React组件首次加载API请求403,刷新后正常的解决方案
问题原因
核心问题是请求实例创建时机与Redux Persist状态恢复不同步:
- 封装
userRequest时,TOKEN是在模块导入阶段直接从localStorage读取的,但此时Redux Persist可能还没完成从本地存储恢复用户状态的操作,导致TOKEN为空,请求头缺少有效认证信息,触发403错误。 - 刷新页面时,
localStorage里的用户状态已经存在,模块重新导入时能读取到有效的TOKEN,所以请求正常通过。
解决方案
方案1:用Axios拦截器动态设置请求头
修改请求封装代码,每次发起请求前实时从localStorage获取最新的TOKEN,避免模块初始化时的状态滞后问题:
import axios from "axios"; const BASE_URL = "http://localhost:5000/api/"; export const publicRequest = axios.create({ baseURL: BASE_URL, }); export const userRequest = axios.create({ baseURL: BASE_URL, }); // 添加请求拦截器,每次请求前动态注入TOKEN userRequest.interceptors.request.use((config) => { const user = JSON.parse(localStorage.getItem("persist:root"))?.user; const currentUser = user && JSON.parse(user).currentUser; const TOKEN = currentUser?.accessToken; if (TOKEN) { config.headers.token = `Bearer ${TOKEN}`; } return config; });
方案2:监听用户状态变化再发起请求
如果项目用了Redux,通过useSelector获取用户状态,将其作为useEffect的依赖项,确保只有当用户状态加载完成后才发起API请求:
import { useSelector } from 'react-redux'; const [orders, setOrders] = useState([]); // 从Redux store获取当前用户 const currentUser = useSelector(state => state.user.currentUser); useEffect(() => { const getOrders = async () => { // 无有效TOKEN时直接返回,避免无效请求 if (!currentUser?.accessToken) return; try { const res = await userRequest.get( "orders/find/63c18620cf0c78c4a0cf7ff9" ); setOrders(res.data); } catch (error) { console.error(error); } }; getOrders(); }, [currentUser]); // 依赖用户状态,状态更新时自动重新请求
方案3:确保Redux Persist状态恢复完成后再渲染组件
使用redux-persist的PersistGate组件,包裹你的根组件,确保只有当状态从本地存储恢复完成后,才渲染页面内容:
import { Provider } from 'react-redux'; import { PersistGate } from 'redux-persist/integration/react'; import { persistStore } from 'redux-persist'; import store from './store'; import App from './App'; const persistor = persistStore(store); ReactDOM.render( <Provider store={store}> {/* loading可以设置为自定义加载组件 */} <PersistGate loading={null} persistor={persistor}> <App /> </PersistGate> </Provider>, document.getElementById('root') );
这种方式下,组件渲染时Redux状态已经完全恢复,模块导入时能读取到有效的TOKEN,首次加载的API请求就能正常携带认证信息。
内容的提问来源于stack exchange,提问作者Herkis
相关产品推荐
相关产品推荐

