MERN栈Redux实现登录时获取userInfo报TypeError问题
MERN栈Redux登录功能报错排查
问题描述
我是编程新手,近期学习使用MERN栈开发用户注册登录功能,后端功能运行无异常,但在前端集成Redux时抛出TypeError报错,报错参考截图:
我已确认Redux store正确关联了reducer、action与常量文件,期望实现将后端返回的登录数据存入userInfo的功能,使用的是最新版本Redux,暂未定位到代码错误。
问题相关代码
SignInScreen.js 登录页组件代码
import React, { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { Link, useLocation, useNavigate } from 'react-router-dom' import { login } from '../actions/userAction' export const SignInScreen = (props, history) => { const navigate = useNavigate const [email, setEmail] = useState('') const [password, setPassword] = useState('') const submitHandler = (e) => { e.preventDefault() dispatch(login(email, password)) } const { search } = useLocation() const redirectInUrl = new URLSearchParams(search).get('redirect') const redirect = redirectInUrl ? redirectInUrl : '/' const userlogin = useSelector((state) => state.userlogin) const { userInfo, loading, error } = userlogin const dispatch = useDispatch() useEffect(() => { if (userInfo) { navigate(redirect) } }, [navigate, userInfo, redirect])
store.js Redux配置代码
import { createStore, combineReducers, applyMiddleware, compose } from 'redux' import thunk from 'redux-thunk' import { userLoginReducer, } from './reducers/userReducer' const userInfo = localStorage.getItem('userInfo') ? JSON.parse(localStorage.getItem('userInfo')) : null const initialState = { userLogin: { userInfo }, } const reducer = combineReducers({ userLogin: userLoginReducer, }) const middleware = [thunk] const store = createStore( reducer, initialState, compose(applyMiddleware(...middleware)) ) export default store
Redux常量定义代码
export const USER_LOGIN_REQUEST = 'USER_LOGIN_REQUEST' export const USER_LOGIN_SUCCESS = 'USER_LOGIN_SUCCESS' export const USER_LOGIN_FAIL = 'USER_LOGIN_FAIL' export const USER_LOGOUT = 'USER_LOGOUT'
userReducer.js 登录状态Reducer代码
import { USER_LOGIN_REQUEST, USER_LOGIN_SUCCESS, USER_LOGIN_FAIL, USER_LOGOUT, } from '../constants/userConstant' function userLoginReducer(state = {}, action) { switch (action.type) { case USER_LOGIN_REQUEST: return { loading: true } case USER_LOGIN_SUCCESS: return { loading: false, userInfo: action.payload } case USER_LOGIN_FAIL: return { loading: false, error: action.payload } case USER_LOGOUT: return {} default: return state } } export userLoginReducer
userAction.js 登录逻辑Action代码
import Axios from 'axios' import { USER_LOGIN_REQUEST, USER_LOGIN_SUCCESS, USER_LOGIN_FAIL, } from '../constants/userConstant' const login = (email, password) => async (dispatch) => { try { dispatch({ type: USER_LOGIN_REQUEST }) const config = { headers: { 'Content-Type': 'application/json' } } const { data } = await Axios.post( '/api/users/login', { email, password }, config ) dispatch({ type: USER_LOGIN_SUCCESS, payload: data }) localStorage.setItem('userInfo', JSON.stringify(data)) } catch (error) { dispatch({ type: USER_LOGIN_FAIL, payload: error.response && error.response.data.message ? error.response.data.message : error.message, }) } } export login
错误点与修复方案
代码中一共存在5处直接导致报错的问题,按优先级修复即可:
- Redux状态读取键名大小写不匹配
store中通过combineReducers注册的登录状态键名为userLogin(驼峰写法,L大写),但组件中useSelector读取时写的是state.userlogin(l小写),Redux状态匹配严格区分大小写,该写法会直接取到undefined,后续解构userInfo时就会抛出TypeError。
修复:将useSelector部分代码修改为
const userLogin = useSelector((state) => state.userLogin) const { userInfo, loading, error } = userLogin- Redux状态读取键名大小写不匹配
- useNavigate Hook调用方式错误
代码中写为const navigate = useNavigate,仅将Hook本身赋值给变量,没有执行Hook拿到导航方法,后续调用navigate(redirect)时会触发"not a function"报错。
修复:修改为const navigate = useNavigate()
- useNavigate Hook调用方式错误
- Hook声明顺序违规
代码中先在submitHandler函数内调用了dispatch,之后才声明const dispatch = useDispatch(),违反React Hook"必须在组件顶层、所有业务逻辑之前声明"的规则,同时会触发暂存死区错误。
修复:将const dispatch = useDispatch()移动到组件最顶部,和其他Hook(useState、useNavigate等)同层级,放在submitHandler定义之前。
- Hook声明顺序违规
- ES模块导出语法错误
userReducer.js中export userLoginReducer、userAction.js中export login均为非法语法,ES模块导出不支持直接写export 变量名的格式,会导致模块导入失败。
修复:
- userReducer.js最后一行修改为
export { userLoginReducer }(和store中的具名导入写法匹配) - userAction.js中login函数声明修改为
export const login = (email, password) => async (dispatch) => {,删除文件最后单独的export login行
- ES模块导出语法错误
- 组件代码不完整
当前贴出的SignInScreen.js没有写return返回JSX的部分,也没有闭合组件函数的大括号,会触发语法错误,记得补全表单渲染的JSX代码和函数闭合。
- 组件代码不完整
内容的提问来源于stack exchange,提问作者Mohamad Salahuddin
相关产品推荐
相关产品推荐

