控制台中未定义的 redux 值
Undefined redux values in console
我正在尝试检查用户是否已登录或未登录 Register.js 组件,但我在其中获得未定义的身份验证状态值。如果您能找到我做错的地方,请调查一下。我已经尝试做了很多改变,但我还是无法做到正确。
感谢大家的帮助。
忽略上下文文件
App.js
import { useEffect } from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import "./App.css";
import { Navbar } from "./components/layout/Navbar";
import { Home } from "./components/pages/Home";
import { MyList } from "./components/favorites/MyList";
import Register from "./components/auth/Register";
import Login from "./components/auth/Login";
import { Provider } from "react-redux";
import store from "./store";
import { loadUser } from "./actions/auth";
import { setAuthToken } from "./utils/setAuthToken";
if (localStorage.token) {
setAuthToken(localStorage.token);
}
function App() {
useEffect(() => {
store.dispatch(loadUser());
}, []);
return (
<Provider store={store}>
<>
<div>
<Navbar />
<Routes>
<Route path='/' element={<Home />} />
<Route path='/mylist' element={<MyList />} />
<Route path='/signin' element={<Login />} />
<Route path='/signup' element={<Register />} />
</Routes>
</div>
</>
</Provider>
);
}
export default App;
Register.js
import React, { useContext, useEffect, useState } from "react";
import { Link, Navigate, useNavigate } from "react-router-dom";
import { connect } from "react-redux";
import { register } from "../../actions/auth";
import axios from "axios";
const Register = ({ register, isAuthenticated, history, location, auth }) => {
const navigate = useNavigate();
const [user, setUser] = useState({
name: "",
email: "",
password: "",
password2: "",
});
const { name, email, password, password2 } = user;
const onFormDataChange = (e) => {
setUser({
...user,
[e.target.name]: e.target.value,
});
};
const onFormSubmit = async (e) => {
e.preventDefault();
register({ name, email, password });
};
console.log(auth);
console.log(isAuthenticated);
return (
<div>
<h1>Sign Up</h1>
<form action='' onSubmit={onFormSubmit}>
<div className='form-group'>
<label htmlFor='name'>Name</label>
<input
type='text'
name='name'
value={name}
onChange={onFormDataChange}
/>
</div>
<div className='form-group'>
<label htmlFor='email'>Email</label>
<input
type='email'
name='email'
value={email}
onChange={onFormDataChange}
/>
</div>
<div className='form-group'>
<label htmlFor='password'>Password</label>
<input
type='password'
name='password'
value={password}
onChange={onFormDataChange}
/>
</div>
<div className='form-group'>
<label htmlFor='password2'>Password</label>
<input
type='password'
name='password2'
value={password2}
onChange={onFormDataChange}
/>
</div>
<input type='submit' value='Signup' />
<p>
Already have an account? <Link to='/signin'>Sign In</Link>
</p>
</form>
</div>
);
};
const mapStateToProps = (state) => {
const { isAuthenticated } = state.auth.isAuthenticated;
const { auth } = state.auth;
return {
isAuthenticated,
};
};
export default connect(mapStateToProps, { register })(Register);
index.js
import { combineReducers } from "redux";
import auth from "./auth";
export default combineReducers({
auth,
});
/auth/types.js
export const REGISTER_SUCCESS = "REGISTER_SUCCESS";
export const REGISTER_FAIL = "REGISTER_FAIL";
export const USER_LOADED = "USER_LOADED";
export const AUTH_ERROR = "AUTH_ERROR";
export const LOGIN_SUCCESS = "LOGIN_SUCCESS";
export const LOGIN_FAIL = "LOGIN_FAIL";
export const LOGOUT = "LOGOUT";
export const CLEAR_ERRORS = "CLEAR_ERRORS";
actions/auth.js
import axios from "axios";
import {
REGISTER_SUCCESS,
REGISTER_FAIL,
USER_LOADED,
AUTH_ERROR,
LOGIN_SUCCESS,
LOGIN_FAIL,
} from "./types";
import { setAuthToken } from "../utils/setAuthToken";
export const loadUser = () => async (dispatch) => {
if (localStorage.token) {
setAuthToken(localStorage.token);
}
try {
const res = await axios.get("/api/auth");
dispatch({
type: USER_LOADED,
payload: res.data,
});
} catch (error) {
dispatch({
type: AUTH_ERROR,
});
}
};
export const register =
({ name, email, password }) =>
async (dispatch) => {
const config = {
headers: {
"Content-Type": "application/json",
},
};
const body = JSON.stringify({ name, email, password });
try {
const res = await axios.post("/api/users", body, config);
dispatch({
type: REGISTER_SUCCESS,
payload: res.data,
});
dispatch(loadUser());
} catch (error) {
dispatch({
type: REGISTER_FAIL,
});
}
};
export const login = (email, password) => async (dispatch) => {
const config = {
headers: {
"Content-Type": "application/json",
},
};
const body = JSON.stringify({ email, password });
try {
const res = await axios.post("/api/auth", body, config);
dispatch({
type: LOGIN_SUCCESS,
payload: res.data,
});
dispatch(loadUser());
} catch (error) {
dispatch({
type: LOGIN_FAIL,
});
}
};
reducers/auth.js
/* eslint-disable default-case */
/* eslint-disable import/no-anonymous-default-export */
import {
REGISTER_SUCCESS,
REGISTER_FAIL,
USER_LOADED,
AUTH_ERROR,
LOGIN_SUCCESS,
LOGIN_FAIL,
} from "../actions/types";
const initalState = {
token: localStorage.getItem("token"),
isAuthenticated: false,
loading: true,
user: null,
};
export default function (state = initalState, action) {
const { type, payload } = action;
switch (type) {
case USER_LOADED:
return {
...state,
user: payload,
isAuthenticated: true,
loading: false,
};
case REGISTER_SUCCESS:
case LOGIN_SUCCESS:
localStorage.setItem("token", payload.token);
return {
...state,
...payload,
isAuthenticated: true,
loading: false,
};
case REGISTER_FAIL:
case AUTH_ERROR:
case LOGIN_FAIL:
localStorage.removeItem("token");
return {
...state,
token: null,
isAuthenticated: false,
loading: true,
};
default:
return state;
}
}
store.js
import { createStore, applyMiddleware } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import thunk from "redux-thunk";
import rootReducer from "./reducers";
const intialState = {};
const middleware = [thunk];
const store = createStore(
rootReducer,
intialState,
composeWithDevTools(applyMiddleware(...middleware))
);
export default store;
我可能是错的,但在你 Register.js
中,在 mapStateToProps
中,你做了以下事情:
const { isAuthenticated } = state.auth.isAuthenticated;
const { auth } = state.auth;
这似乎是不正确的,除非你的州有以下结构:
{
auth: {
isAuthenticated: { isAuthenticated: *value here* },
auth: *value here*
}
}
我认为,这里可能是错误的,你应该按照以下方式解构值:
const { isAuthenticated } = state.auth;
const { auth } = state;
我正在尝试检查用户是否已登录或未登录 Register.js 组件,但我在其中获得未定义的身份验证状态值。如果您能找到我做错的地方,请调查一下。我已经尝试做了很多改变,但我还是无法做到正确。
感谢大家的帮助。
忽略上下文文件
App.js
import { useEffect } from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import "./App.css";
import { Navbar } from "./components/layout/Navbar";
import { Home } from "./components/pages/Home";
import { MyList } from "./components/favorites/MyList";
import Register from "./components/auth/Register";
import Login from "./components/auth/Login";
import { Provider } from "react-redux";
import store from "./store";
import { loadUser } from "./actions/auth";
import { setAuthToken } from "./utils/setAuthToken";
if (localStorage.token) {
setAuthToken(localStorage.token);
}
function App() {
useEffect(() => {
store.dispatch(loadUser());
}, []);
return (
<Provider store={store}>
<>
<div>
<Navbar />
<Routes>
<Route path='/' element={<Home />} />
<Route path='/mylist' element={<MyList />} />
<Route path='/signin' element={<Login />} />
<Route path='/signup' element={<Register />} />
</Routes>
</div>
</>
</Provider>
);
}
export default App;
Register.js
import React, { useContext, useEffect, useState } from "react";
import { Link, Navigate, useNavigate } from "react-router-dom";
import { connect } from "react-redux";
import { register } from "../../actions/auth";
import axios from "axios";
const Register = ({ register, isAuthenticated, history, location, auth }) => {
const navigate = useNavigate();
const [user, setUser] = useState({
name: "",
email: "",
password: "",
password2: "",
});
const { name, email, password, password2 } = user;
const onFormDataChange = (e) => {
setUser({
...user,
[e.target.name]: e.target.value,
});
};
const onFormSubmit = async (e) => {
e.preventDefault();
register({ name, email, password });
};
console.log(auth);
console.log(isAuthenticated);
return (
<div>
<h1>Sign Up</h1>
<form action='' onSubmit={onFormSubmit}>
<div className='form-group'>
<label htmlFor='name'>Name</label>
<input
type='text'
name='name'
value={name}
onChange={onFormDataChange}
/>
</div>
<div className='form-group'>
<label htmlFor='email'>Email</label>
<input
type='email'
name='email'
value={email}
onChange={onFormDataChange}
/>
</div>
<div className='form-group'>
<label htmlFor='password'>Password</label>
<input
type='password'
name='password'
value={password}
onChange={onFormDataChange}
/>
</div>
<div className='form-group'>
<label htmlFor='password2'>Password</label>
<input
type='password'
name='password2'
value={password2}
onChange={onFormDataChange}
/>
</div>
<input type='submit' value='Signup' />
<p>
Already have an account? <Link to='/signin'>Sign In</Link>
</p>
</form>
</div>
);
};
const mapStateToProps = (state) => {
const { isAuthenticated } = state.auth.isAuthenticated;
const { auth } = state.auth;
return {
isAuthenticated,
};
};
export default connect(mapStateToProps, { register })(Register);
index.js
import { combineReducers } from "redux";
import auth from "./auth";
export default combineReducers({
auth,
});
/auth/types.js
export const REGISTER_SUCCESS = "REGISTER_SUCCESS";
export const REGISTER_FAIL = "REGISTER_FAIL";
export const USER_LOADED = "USER_LOADED";
export const AUTH_ERROR = "AUTH_ERROR";
export const LOGIN_SUCCESS = "LOGIN_SUCCESS";
export const LOGIN_FAIL = "LOGIN_FAIL";
export const LOGOUT = "LOGOUT";
export const CLEAR_ERRORS = "CLEAR_ERRORS";
actions/auth.js
import axios from "axios";
import {
REGISTER_SUCCESS,
REGISTER_FAIL,
USER_LOADED,
AUTH_ERROR,
LOGIN_SUCCESS,
LOGIN_FAIL,
} from "./types";
import { setAuthToken } from "../utils/setAuthToken";
export const loadUser = () => async (dispatch) => {
if (localStorage.token) {
setAuthToken(localStorage.token);
}
try {
const res = await axios.get("/api/auth");
dispatch({
type: USER_LOADED,
payload: res.data,
});
} catch (error) {
dispatch({
type: AUTH_ERROR,
});
}
};
export const register =
({ name, email, password }) =>
async (dispatch) => {
const config = {
headers: {
"Content-Type": "application/json",
},
};
const body = JSON.stringify({ name, email, password });
try {
const res = await axios.post("/api/users", body, config);
dispatch({
type: REGISTER_SUCCESS,
payload: res.data,
});
dispatch(loadUser());
} catch (error) {
dispatch({
type: REGISTER_FAIL,
});
}
};
export const login = (email, password) => async (dispatch) => {
const config = {
headers: {
"Content-Type": "application/json",
},
};
const body = JSON.stringify({ email, password });
try {
const res = await axios.post("/api/auth", body, config);
dispatch({
type: LOGIN_SUCCESS,
payload: res.data,
});
dispatch(loadUser());
} catch (error) {
dispatch({
type: LOGIN_FAIL,
});
}
};
reducers/auth.js
/* eslint-disable default-case */
/* eslint-disable import/no-anonymous-default-export */
import {
REGISTER_SUCCESS,
REGISTER_FAIL,
USER_LOADED,
AUTH_ERROR,
LOGIN_SUCCESS,
LOGIN_FAIL,
} from "../actions/types";
const initalState = {
token: localStorage.getItem("token"),
isAuthenticated: false,
loading: true,
user: null,
};
export default function (state = initalState, action) {
const { type, payload } = action;
switch (type) {
case USER_LOADED:
return {
...state,
user: payload,
isAuthenticated: true,
loading: false,
};
case REGISTER_SUCCESS:
case LOGIN_SUCCESS:
localStorage.setItem("token", payload.token);
return {
...state,
...payload,
isAuthenticated: true,
loading: false,
};
case REGISTER_FAIL:
case AUTH_ERROR:
case LOGIN_FAIL:
localStorage.removeItem("token");
return {
...state,
token: null,
isAuthenticated: false,
loading: true,
};
default:
return state;
}
}
store.js
import { createStore, applyMiddleware } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import thunk from "redux-thunk";
import rootReducer from "./reducers";
const intialState = {};
const middleware = [thunk];
const store = createStore(
rootReducer,
intialState,
composeWithDevTools(applyMiddleware(...middleware))
);
export default store;
我可能是错的,但在你 Register.js
中,在 mapStateToProps
中,你做了以下事情:
const { isAuthenticated } = state.auth.isAuthenticated;
const { auth } = state.auth;
这似乎是不正确的,除非你的州有以下结构:
{
auth: {
isAuthenticated: { isAuthenticated: *value here* },
auth: *value here*
}
}
我认为,这里可能是错误的,你应该按照以下方式解构值:
const { isAuthenticated } = state.auth;
const { auth } = state;