MERN+Redux Toolkit认证系统条件渲染异常问题求助
MERN认证系统Redux Toolkit条件渲染异常问题
我用Redux Toolkit构建MERN认证系统,配置看起来正常,但条件渲染功能异常:初始状态下currentUser为null,Login组件本该渲染登录页面,却错误渲染了仅在有用户时才显示的UpdateProfile组件,且Redux DevTools显示currentUser确实为null。
相关代码
1. auth Slice代码
import { createSlice } from "@reduxjs/toolkit"; const authSlice = createSlice({ name: "auth", initialState: { currentUser: null, isFetching: false, error: false, }, reducers: { reset: (state) => { state.currentUser = null; state.isFetching = false; state.error = false; }, loginStart: (state) => { state.isFetching = true; }, loginSuccess: (state, action) => { state.isFetching = false; state.currentUser = action.payload; }, loginFail: (state) => { state.isFetching = false; state.error = true; }, registerStart: (state) => { state.isFetching = true; }, registerSuccess: (state, action) => { state.isFetching = false; state.currentUser = action.payload; }, registerFail: (state) => { state.isFetching = false; state.error = true; }, logoutSuccess: (state) => { (state.currentUser = null), (state.isFetching = false), (state.error = false); }, }, }); export const { reset, loginStart, loginSuccess, loginFail, registerStart, registerSuccess, registerFail, } = authSlice.actions; export default authSlice.reducer;
2. store配置代码
import { configureStore } from "@reduxjs/toolkit"; import authReducer from './authRedux' import storage from 'redux-persist/lib/storage' import { persistReducer, persistStore, FLUSH, REHYDRATE, REGISTER, PURGE, PERSIST } from 'redux-persist'; const persistConfig={ key:'root', version: 1, storage, } const persistedReducer = persistReducer(persistConfig, authReducer); export const store = configureStore({ reducer:{ auth: persistedReducer, }, middleware:(getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck:{ ignoreActions:[FLUSH,REGISTER,REHYDRATE,PERSIST,PURGE], }, }) }); export let persistor = persistStore(store);
3. Login组件代码
import React, { useState } from "react"; import { Form, Card, Button, Alert } from "react-bootstrap"; import { Link, useNavigate } from "react-router-dom"; import { useDispatch, useSelector } from "react-redux"; import { login } from "../../Redux/apiCalls"; import UpdateProfile from "../UpdateProfile/Updateprofile"; export default function Login() { const [username, setUserName] = useState(""); const [password, setPassword] = useState(""); const dispatch = useDispatch(); const currentUser = useSelector((state) => state.auth); const { isFetching, error } = useSelector((state) => state.auth); const navigate = useNavigate(); async function handleSubmit(e) { e.preventDefault(); try { if(!currentUser){ navigate('/') }else{ login(dispatch, { username, password }); navigate('/'); } } catch (error) { console.log(error); } } console.log(currentUser); return ( <> {currentUser ? (<UpdateProfile/>):( <Card className="shadow-lg p-3 mb-2 bg-white rounded"> <Card.Body> <h2 className="text-center mb-4">Log In</h2> {error && <Alert variant="danger">{error}</Alert>} <Form onSubmit={handleSubmit}> <Form.Group id="username"> <Form.Label>UserName</Form.Label> <Form.Control type="text" required onChange={(e) => setUserName(e.target.value)} /> </Form.Group> <Form.Group id="password"> <Form.Label>Password</Form.Label> <Form.Control type="password" required onChange={(e) => setPassword(e.target.value)} /> </Form.Group> <Button disabled={isFetching} className="w-100 mt-4 mb-4" type="submit" > Log In </Button> </Form> <div className="w-100 text-center mt-2"> <Link to="/forgot-password">Forgot Password</Link> </div> <div className="w-100 text-center mt-3"> Need an Account? <Link to="/signup">Sing Up</Link> </div> </Card.Body> </Card> )} </> ); }
问题分析与修复方案
核心问题
Login组件中,你通过useSelector获取的currentUser是整个auth状态对象(包含currentUser、isFetching、error三个属性),而不是对象内部的currentUser字段。由于对象本身永远是非空值,条件判断{currentUser ? <UpdateProfile/> : ...}永远为真,导致错误渲染UpdateProfile组件。
修复步骤
修正state选择逻辑
将Login组件中获取currentUser的代码:const currentUser = useSelector((state) => state.auth);修改为:
const currentUser = useSelector((state) => state.auth.currentUser);这样才能正确获取到初始为null的
currentUser字段值。修正handleSubmit逻辑
原提交逻辑的判断逻辑写反了,应该是无用户时执行登录请求:async function handleSubmit(e) { e.preventDefault(); try { if (!currentUser) { login(dispatch, { username, password }); navigate('/'); } else { navigate('/'); } } catch (error) { console.log(error); } }可选优化:合并useSelector调用
可以把多个state选择合并为一次调用,减少重复操作:const { currentUser, isFetching, error } = useSelector((state) => state.auth);
内容的提问来源于stack exchange,提问作者smit agravat
相关产品推荐
相关产品推荐

