如何在React TypeScript+Redux Toolkit中存储后端返回的全部用户数据
问题:React TypeScript + Redux Toolkit 无法存储完整用户数据
我使用React TypeScript搭配Redux Toolkit,在获取用户信息时遇到问题:state.user只能存储单个值,希望它能存储后端返回的全部用户数据。
现有代码
userSlice.ts
export const userSlice = createSlice({ name: "user", initialState: { user: null, }, reducers: { setUser: (state, action) => { state.user = action.payload; }, }, });
protectedRoute.tsx(部分代码)
export function ProtectedRoute(props: { children: any }) { const {user} = useSelector((state: any) => state.user); const dispatch = useDispatch(); const navigate = useNavigate(); const getUser = async () => { try { dispatch(showLoading()); const response = await axios.post( "/api/users/user", { token: localStorage.getItem("token") }, { headers: { Authorization: `Bearer ${localStorage.getItem("token")}`, }, } ); dispatch(hideLoading()); if (response.data.success) { console.log(response.data.data.isAdmin); dispatch(setUser(response.data.data));
解决方案
1. 定义用户数据类型(TypeScript类型约束)
先明确后端返回的用户结构,创建对应的TypeScript接口,避免any导致的类型模糊问题:
// 根据后端实际返回的字段调整 interface User { id: string; username: string; isAdmin: boolean; email?: string; // 可选字段示例 // 补充其他用户字段 }
2. 更新userSlice的类型与逻辑
将initialState和reducer的payload都加上类型约束,确保可以接收完整的用户对象:
import { createSlice, PayloadAction } from '@reduxjs/toolkit'; interface User { id: string; username: string; isAdmin: boolean; // 补充后端返回的所有字段 } interface UserState { user: User | null; } const initialState: UserState = { user: null, }; export const userSlice = createSlice({ name: "user", initialState, reducers: { setUser: (state, action: PayloadAction<User>) => { // 直接赋值完整的payload对象,即可存储全部用户数据 state.user = action.payload; }, }, }); export const { setUser } = userSlice.actions; export default userSlice.reducer;
3. 优化ProtectedRoute的类型使用
从store中导出RootState类型,替代any,让TypeScript做类型校验:
// 首先在store.ts中导出RootState和AppDispatch类型 // store.ts示例代码: import { configureStore } from '@reduxjs/toolkit'; import userReducer from './userSlice'; export const store = configureStore({ reducer: { user: userReducer, }, }); export type RootState = ReturnType<typeof store.getState>; export type AppDispatch = typeof store.dispatch;
然后在ProtectedRoute中使用这些类型:
import { RootState, AppDispatch } from './store'; import { useDispatch, useSelector } from 'react-redux'; import { useEffect } from 'react'; export function ProtectedRoute(props: { children: React.ReactNode }) { const { user } = useSelector((state: RootState) => state.user); const dispatch = useDispatch<AppDispatch>(); const navigate = useNavigate(); const getUser = async () => { try { dispatch(showLoading()); const response = await axios.post( "/api/users/user", { token: localStorage.getItem("token") }, { headers: { Authorization: `Bearer ${localStorage.getItem("token")}`, }, } ); dispatch(hideLoading()); if (response.data.success) { // 确认response.data.data是完整用户对象 console.log('完整用户数据:', response.data.data); dispatch(setUser(response.data.data)); } } catch (error) { dispatch(hideLoading()); navigate('/login'); // 请求失败跳转登录 } }; useEffect(() => { if (!user) { getUser(); } }, [user, navigate, dispatch]); return user ? props.children : <div>加载中...</div>; }
4. 验证后端返回数据
确保后端接口/api/users/user返回的response.data.data是包含所有用户字段的对象,而非单个值。如果后端返回的是数组或其他结构,需要对应调整User类型和slice的处理逻辑。
内容的提问来源于stack exchange,提问作者Ahmed Ben Bettaieb
相关产品推荐
相关产品推荐

