React Redux登录功能异常:无法跳转Profile页及显示错误
React Redux登录功能异常排查求助
我用React Redux实现了注册和登录功能,期望登录成功后跳转至Profile页面,出错时显示错误信息。注册页功能正常,但登录页既不跳转也不显示错误提示。两者代码几乎一致,作为新手不知道怎么调试。控制台显示useSelector获取state.auth.user为空,但Profile页的相同useSelector代码却能正常工作。
main.jsx
import React from 'react' import ReactDOM from 'react-dom/client' import App from './App' import "./index.css" import axios from 'axios' import { store } from './store/store.jsx' import { Provider } from 'react-redux' import { createBrowserRouter, createRoutesFromElements, Route, RouterProvider } from 'react-router-dom' import SignupForm from './Components/signup' import SigninForm from './Components/signin' import RootLayout from './Components/root-layout' import ErrorPage from './Components/error-page' import ProfilePage from './Components/profile' const router = createBrowserRouter( createRoutesFromElements(( <Route path='/' element={<RootLayout />}> <Route path='/' element={<App />}></Route> <Route path='/signup' element={<SignupForm />} ></Route> <Route path='/signin' element={<SigninForm />} ></Route> <Route path='*' element={<ErrorPage />}></Route> <Route path='/profile' element={<ProfilePage />}></Route> </Route> ) )) ReactDOM.createRoot(document.getElementById('root')).render( <React.StrictMode> <Provider store={store}> <RouterProvider router={router} /> </Provider> </React.StrictMode>, )
store.jsx
import { configureStore } from '@reduxjs/toolkit' import authSlice from './authSlice' export const store = configureStore({ reducer: { auth: authSlice } })
authSlice.jsx
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"; import axios from "axios"; export const signup = createAsyncThunk('auth/signup', async({username, password}, thunkAPI) => { try { const res = await axios.post('http://localhost:8080/signup', {username, password}) return res.data } catch (err) { console.log(err) return thunkAPI.rejectWithValue(err.message) } }) export const signin = createAsyncThunk('auth/signin', async({username, password}) => { try { const res = await axios.post('http://localhost:8080/signin', {username, password}) return res.data } catch (err) { return thunkAPI.rejectWithValue(err.response.data) } }) const initialState = { user: '', isLoggedIn: false, loading: false, error:null } export const authSlice = createSlice({ name: 'auth', initialState, reducers: { logout: (state, action) => { state.user = '' state.isLoggedIn = false state.loading = false state.error = null } }, extraReducers: (builder) => { builder .addCase(signup.fulfilled, (state, action) => { state.user = action.payload.username state.isLoggedIn = true state.loading = false state.error = null }) .addCase(signup.pending, (state, action) => { state.loading = true }) .addCase(signup.rejected, (state, action) => { state.loading = false state.isLoggedIn = false state.error = action.payload }) .addCase(signin.fulfilled, (state, action) => { state.user = action.payload.username state.isLoggedIn = true state.loading = false state.error = null }) .addCase(signin.pending, (state, action) => { state.loading = true }) .addCase(signin.rejected, (state, action) => { state.loading = false state.isLoggedIn = false state.error = action.payload }) } }) export const { logout } = authSlice.actions export default authSlice.reducer
profile.jsx
import { useSelector } from "react-redux" export default function ProfilePage () { const user = useSelector((state) => state.auth.user) //这个useSelector能正常工作 return ( <div> <h3>Profile</h3> {user ? <div>Hi, {user}!</div> : null} </div> ) }
signup.jsx
import { useDispatch, useSelector } from "react-redux"; import { Navigate } from "react-router-dom"; import { signup } from "../store/authSlice"; export default function SignupForm () { const [username, setUsername] = useState('') const [password, setPassword] = useState('') const user = useSelector((state) => state.auth.user) const error = useSelector((state) => state.auth.error) //这两个useSelector在console.log时看似不工作,但功能正常 const dispatch = useDispatch() const submitHandler = e => { e.preventDefault() dispatch(signup({username, password})) .then((res) => { setPassword('') setUsername('') }) console.log(user) console.log(error) } return ( <div> <form onSubmit={submitHandler}> <div>Sign up</div> <div> <label htmlFor="username">Username:</label> <input id="username" type="text" value={username} onChange={(e) => setUsername(e.target.value)} minLength={1} maxLength={60}/> </div> <div> <label htmlFor="password">Password:</label> <input id="password" type="password" value={password} onChange={(e) => setPassword(e.target.value)} minLength={1}/> </div> <div> <button>Cancel</button> <button type="submit">Submit</button> </div> {error ? <p>{error}</p> : null} {user ? <Navigate to='/profile' replace={true} /> : null} </form> </div> ) }
signin.jsx
import React, { useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { Navigate } from "react-router-dom"; import { signin } from "../store/authSlice"; export default function SigninForm () { const [username, setUsername] = useState('') const [password, setPassword] = useState('') const user = useSelector((state) => state.auth.user) const error = useSelector((state) => state.auth.error) //这两个useSelector不工作 ^ const dispatch = useDispatch() const submitHandler = e => { e.preventDefault() dispatch(signin({username, password})) .then((res) => { setPassword('') setUsername('') }) console.log(user) console.log(error) } return ( <div> <form onSubmit={submitHandler}> <div>Sign in</div> <div> <label htmlFor="username">Username:</label> <input id="username" type="text" value={username} onChange={(e) => setUsername(e.target.value)} minLength={1} maxLength={60}/> </div> <div> <label htmlFor="password">Password:</label> <input id="password" type="password" value={password} onChange={(e) => setPassword(e.target.value)} minLength={1}/> </div> <div> <button>Cancel</button> <button type="submit">Submit</button> </div> {error ? <div>{error}</div> : null} {user ? <Navigate to='/profile' replace={true} /> : null} //这两个部分在注册页正常,登录页失效 ^ </form> </div> ) }
控制台输出
登录页console.log显示user为空字符串,error为null。
问题修复方案
1. 修复signin异步Thunk参数缺失
authSlice.jsx中signin异步Thunk未接收thunkAPI参数,导致错误处理时无法调用thunkAPI.rejectWithValue,修正如下:
export const signin = createAsyncThunk('auth/signin', async({username, password}, thunkAPI) => { try { const res = await axios.post('http://localhost:8080/signin', {username, password}) return res.data } catch (err) { // 兼容接口返回异常的情况 return thunkAPI.rejectWithValue(err.response?.data || err.message) } })
2. 校验登录接口返回格式
确保后端/signin接口返回的数据结构包含username字段,与注册接口一致。若返回格式不同(比如{user: {username: 'xxx'}}),需同步修改signin.fulfilled逻辑:
.addCase(signin.fulfilled, (state, action) => { // 根据实际返回结构调整取值路径 state.user = action.payload.username || action.payload.user?.username state.isLoggedIn = true state.loading = false state.error = null })
3. 修正组件状态监听逻辑
组件内console.log在dispatch执行后立即打印,此时Redux状态尚未更新,属于正常现象。可改用useEffect监听状态变化:
// 在signin.jsx中添加 import { useEffect } from 'react'; useEffect(() => { console.log('当前user:', user) console.log('当前error:', error) }, [user, error])
4. 补充signup.jsx缺失的导入
signup.jsx未导入useState,会导致运行错误,需补充:
import React, { useState } from "react";
内容的提问来源于stack exchange,提问作者Cian Neiland
相关产品推荐
相关产品推荐

