React+Django Djoser登录系统报错:无法解构undefined的loading属性
React+Django(Djoser)登录系统报错修复
错误信息
Unexpected Application Error!
Cannot destructure property 'loading' of '(0 , react_redux__WEBPACK_IMPORTED_MODULE_3__.useSelector)(...)' as it is undefined.
TypeError: Cannot destructure property 'loading' of '(0 , react_redux__WEBPACK_IMPORTED_MODULE_3__.useSelector)(...)' as it is undefined.
问题分析
- 核心错误:
login.js中使用useSelector((state) => state.user)获取状态,但你的Redux store里注册的reducer分支是auth(见store.js中的reducer: { auth: authReducer }),状态路径不匹配导致返回undefined,无法解构loading属性。 - 次要错误:
authActions.js里的Content-Type拼写错误,写成了applicatiom/json,会导致请求格式异常。
修复步骤
1. 修正login.js中的状态路径
将错误的状态获取代码替换为正确的路径,同时添加默认值避免解构报错:
// 原代码 const { loading, userInfo, error } = useSelector((state) => state.user) // 修正后 const { loading, userInfo, error } = useSelector((state) => state.auth || {})
2. 修正authActions.js中的请求头拼写
修复Content-Type的拼写错误:
// 原代码 'Content-Type': 'applicatiom/json', // 修正后 'Content-Type': 'application/json',
可选优化:优化状态初始化
在authSlice.js中,将userInfo的初始值从空对象改为null,让登录状态判断更严谨:
const initialState = { loading: false, userInfo: null, // 原值为{} userToken, error: null, success: false, }
修正后的关键代码片段
login.js(修正后)
import { useForm } from 'react-hook-form' import { useDispatch, useSelector } from 'react-redux'; import { useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { userLoggin } from '../features/auth/authActions'; const Login = () => { const { loading, userInfo, error } = useSelector((state) => state.auth || {}) const dispatch = useDispatch() const { register, handleSubmit } = useForm() const navigate = useNavigate() useEffect(() => { if (userInfo) { navigate ('/user-profile') } }, [navigate, userInfo]) const submitForm = (data) => { dispatch(userLoggin(data)) } return ( <form className="mb-3" onSubmit={handleSubmit(submitForm)}> {error && <h3>{error}</h3>} <div className='form-group'> <label htmlFor='email'>Email</label> <input type='email' className='form-input' {...register('email')} required /> </div> <div className='form-group'> <label htmlFor='password'>Password</label> <input type='password' className='form-input' {...register('password')} required /> </div> <button type='submit' className='button' > {loading ? <h3>loading...</h3> : 'Login'} </button> </form> ) }; export default Login;
authActions.js(修正后)
import axios from 'axios'; import { createAsyncThunk } from '@reduxjs/toolkit'; const backendURL = 'http://127.0.0.1:8000' export const userLoggin = createAsyncThunk( 'auth/login', async ({email, password }, [rejectWithValue]) => { try { const config = { headers : { 'Content-Type': 'application/json', }, } const { data } = await axios.post( `${backendURL}/auth/jwt/create/`, { email, password }, config ) localStorage.setItem('userToken', data.userToken) return data } catch (error) { if (error.response && error.response.data.message) { return rejectWithValue (error.response.message) } else { return rejectWithValue (error.message) } } } )
内容的提问来源于stack exchange,提问作者Arthur Bella
相关产品推荐
相关产品推荐

