如何使用Redux Toolkit自动获取API数据实现用户授权校验
使用Redux Toolkit实现全局用户授权状态管理
需求描述
我需要从/api/auth/profile接口获取token解析后的用户数据,以此判断用户是否授权,开放对应功能。要求网站加载时自动获取数据,且能在多页面复用,请问如何用Redux Toolkit实现?
我尝试过的代码
Redux Slice基础实现:
import { createSlice,createAsyncThunk } from "@reduxjs/toolkit"; export const fetchUserInfo = createAsyncThunk("fetchUserInfo", async () => { const res = await fetch("http://localhost:8800/api/auth/profile") return res.json() }) const userInfo = createSlice({ name:"userInfo", initialState:{ data:null }, extraReducers: (builder) => { builder.addCase(fetchUserInfo.fulfilled, (state,action) => { state.data = action.payload; }) } }) export default userInfo.reducer;
尝试过的触发方式:
import { fetchUserInfo } from '../../redux/userSlice'; setTimeout(()=>{ dispatch(fetchUserInfo()) console.log("implemented") },1000)
另外试过RTK Query,但遇到Redux Store Provider与Api Provider冲突的问题。
解决方案
一、完善Redux Slice的状态管理
你的基础Slice缺少加载、错误状态的处理,以及授权状态的直接维护,补充后更便于页面判断:
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"; export const fetchUserInfo = createAsyncThunk("userInfo/fetchUserInfo", async (_, { rejectWithValue }) => { try { const res = await fetch("http://localhost:8800/api/auth/profile", { credentials: 'include', // 若token存在Cookie中需添加;若存在localStorage,要在headers里带Authorization headers: { // 示例:token存在localStorage时添加 // 'Authorization': `Bearer ${localStorage.getItem('token')}` } }); if (!res.ok) throw new Error('获取用户信息失败'); return await res.json(); } catch (err) { return rejectWithValue(err.message); } }); const userInfoSlice = createSlice({ name: "userInfo", initialState: { data: null, loading: false, error: null, isAuthenticated: false // 直接维护授权状态,避免页面重复判断 }, reducers: { // 手动登出时清空状态 logout: (state) => { state.data = null; state.isAuthenticated = false; state.error = null; } }, extraReducers: (builder) => { builder .addCase(fetchUserInfo.pending, (state) => { state.loading = true; state.error = null; }) .addCase(fetchUserInfo.fulfilled, (state, action) => { state.loading = false; state.data = action.payload; state.isAuthenticated = true; // 接口返回有效数据即视为已授权 }) .addCase(fetchUserInfo.rejected, (state, action) => { state.loading = false; state.error = action.payload; state.isAuthenticated = false; // 请求失败/未授权则标记为未登录 }); } }); export const { logout } = userInfoSlice.actions; export default userInfoSlice.reducer;
二、配置Redux Store
确保Store正确挂载这个reducer:
import { configureStore } from "@reduxjs/toolkit"; import userInfoReducer from './userSlice'; export const store = configureStore({ reducer: { userInfo: userInfoReducer, // 其他项目reducer... } });
三、全局自动触发用户信息获取
不要用setTimeout这种不可靠的方式,直接在App根组件的useEffect中触发:
import { useEffect } from 'react'; import { useDispatch } from 'react-redux'; import { fetchUserInfo } from './redux/userSlice'; function App() { const dispatch = useDispatch(); useEffect(() => { // 页面初始化时立即请求用户信息 dispatch(fetchUserInfo()); }, [dispatch]); return ( // 你的路由和页面组件 ); } export default App;
四、多页面中使用授权状态
在任意组件中通过useSelector获取状态,快速判断授权情况:
import { useSelector } from 'react-redux'; function ProtectedComponent() { const { isAuthenticated, loading, data } = useSelector(state => state.userInfo); if (loading) return <div>加载中...</div>; if (!isAuthenticated) return <div>请先登录</div>; return ( <div>欢迎你,{data.username}</div> ); }
解决RTK Query的Provider冲突问题
之前的冲突是因为RTK Query的Api Provider需要和Redux Store共用同一个Store,正确配置方式如下:
// api.js import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; export const userApi = createApi({ reducerPath: 'userApi', baseQuery: fetchBaseQuery({ baseUrl: 'http://localhost:8800/api/', credentials: 'include' // 或携带Authorization头,根据token存储方式选择 }), endpoints: (builder) => ({ getUserInfo: builder.query({ query: () => 'auth/profile' }) }) }); export const { useGetUserInfoQuery } = userApi; // store.js import { configureStore } from "@reduxjs/toolkit"; import { userApi } from './api'; export const store = configureStore({ reducer: { [userApi.reducerPath]: userApi.reducer, // 其他reducer... }, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(userApi.middleware) }); // App.js import { Provider } from 'react-redux'; import { store } from './redux/store'; function App() { return ( <Provider store={store}> {/* 你的组件 */} </Provider> ); }
配置完成后,直接在组件中调用useGetUserInfoQuery()即可自动获取数据,无需额外的Api Provider。
内容的提问来源于stack exchange,提问作者ABC BakhramovVv
相关产品推荐
相关产品推荐

