Redux useSelector返回undefined但状态已设置的问题求助
Redux useSelector获取用户名/Token返回undefined问题
我正在开发Twitter(X)复刻项目,采用Redux进行状态管理,通过redux-persist实现持久化登录,将用户的用户名和token存储在Redux(遵循最佳实践)及localStorage中。项目包含主页和个人资料页,分别用于展示帖子列表与个人资料页面。
目前遇到的核心问题:在主页和个人资料页使用useSelector获取token与用户名时,返回值为undefined。但通过控制台打印状态、查看Redux DevTools,均显示状态已正确设置,却无法正常获取对应值。我已查阅Stack Overflow上的类似案例,但未找到适配的解决方案。
个人资料页代码
'use client' import { IconButton, Typography, Avatar, Button } from '@mui/material' import React from 'react' import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import Link from 'next/link'; import Image from 'next/image'; import moment from 'moment'; import CalendarMonthIcon from '@mui/icons-material/CalendarMonth'; import ProfileHeaderCategories from '../components/ProfileHeaderCategories'; import { selectAuthToken,selectAuthUser } from '../store/selectors/authSelectors'; import { useSelector } from 'react-redux'; let registrationDate = moment().format('[Joined] MMMM Do YYYY').toString() const backgroundImageUrl = "/" const Profile = () => { const username = useSelector(selectAuthUser); const token = useSelector(selectAuthToken) console.log(username, token) // returns undefined return ( <main className='border-r-[0.5px] border-r-gray-600 w-[600px] max-w-[650px]'> <div className='flex items-center pl-2 mb-2'> <Link href="/home"> <IconButton sx={{ padding: 1, marginTop: 1, }} className='hover:bg-[#293640] mr-4' > <ArrowBackIcon className='text-white rounded-full text-[20px] font-bold' /> </IconButton> </Link> <Typography variant="h6" className='font-bold'> {username} </Typography> </div> <Image src={backgroundImageUrl} alt="Background Profile pic" width={500} height={500} /> <div className='flex justify-between'> <Avatar sx={{ width: 120, height: 120, position: 'absolute', transform: 'translateY(-50%)', marginLeft: 2, }} className='border-4 border-[#15202b]' /> </div> <Button className='text-white font-bold bg-[15202b] rounded-full border-gray-600 capitalize float-right' sx={{ border: 0.5, borderColor: "gray", marginTop: 1, marginRight: 1, padding: 1, }} >Edit profile</Button> <div className='flex flex-col mt-16'> <span className='px-4 font-bold text-xl'>{`Your name`}</span> <span className='text-gray-400 text-base px-4'>{username}</span> <div className='text-base text-gray-400 pt-4 px-4 mb-4'> <CalendarMonthIcon sx={{ fontSize: 'medium', marginRight: 1, }} /> {registrationDate} </div> </div> <div className='border-b-[0.5px] border-b-slate-500'> <ProfileHeaderCategories /> </div> </main> ) } export default Profile
authReducer代码
import { createSlice } from '@reduxjs/toolkit'; const authReducer= createSlice({ name: 'auth', initialState: { username: null, token: null, showSignIn: true, }, reducers: { setUsername: (state, action) => { console.log('Before set name:', state.username); state.username = action.payload; console.log('After set name:', state.username); }, setToken: (state, action) => { console.log('Before setting token:', state.token); state.token = action.payload; console.log('After setting token:', state.token); }, logout: (state) => { state.username = null; state.token = null; localStorage.clear() }, toggleShowSignIn: (state) => { console.log('Before toggle:', state.showSignIn); state.showSignIn = !state.showSignIn console.log('After toggle:', state.showSignIn); } } }); export const { setUsername, setToken, logout, toggleShowSignIn } = authReducer.actions; export default authReducer.reducer;
Store配置代码
'use client' import { configureStore, combineReducers } from "@reduxjs/toolkit"; import postSlice from "./slices/postSlice"; import signUpReducer from "./reducers/signUpReducer"; import signInReducer from "./reducers/signInReducer"; import authSlice from "./slices/authSlice"; import storage from 'redux-persist/lib/storage'; import { PersistPartial } from "redux-persist/es/persistReducer"; import { persistReducer, FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER, } from 'redux-persist' // RootState type to include persisted state export type RootState = ReturnType<typeof rootReducer> & PersistPartial; const persistConfig = { key: 'signData', storage, whitelist: ['auth'],// only the 'auth' reducer in persisted state }; // Combine reducers const rootReducer = combineReducers({ posts: postSlice, signUpForm: signUpReducer, signIn: signInReducer, auth: authSlice, }); // Create persisted reducer const persistedReducer = persistReducer(persistConfig, rootReducer); const store = configureStore({ reducer: persistedReducer, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: { ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER], }, }) }) export default store;
选择器代码
import { RootState } from "../store"; export interface UsernameAuth { username: string } export interface TokenAuth { token: string } export const selectAuthUser = (state: UsernameAuth) => state.username; export const selectAuthToken = (state: TokenAuth) => state.token; export const selectShowSignIn = (state: RootState) => state.auth.showSignIn;
已尝试的解决方法
我曾改写useSelector的调用方式,例如:
const tokenCheck = useSelector((state) => selectAuthToken(state))
但问题仍未解决。
内容的提问来源于stack exchange,提问作者Akk1
相关产品推荐
相关产品推荐

