无法读取未定义的 reactjs JWT 身份验证的属性“令牌”
Posted
技术标签:
【中文标题】无法读取未定义的 reactjs JWT 身份验证的属性“令牌”【英文标题】:Cannot read property 'token' of undefined reactjs JWT Authentication 【发布时间】:2021-07-06 00:22:28 【问题描述】:有人可以帮我解决我所缺少的吗?当我尝试登录时,如果凭据正确,它应该重定向到个人资料页面,如果不是,它应该在登录按钮下方显示来自服务器 server response message screenshot 的响应消息,例如 Invalid Password ! 而不是它重定向到个人资料页面,如果登录凭据错误,则会显示此错误Error Screenshot,它应该在登录按钮下方显示错误消息,如果登录成功,它应该重定向到个人资料页面。
auth.service.js
const login = (username, password) =>
return axios
.post(API_URL + "signin",
username,
password,
)
.then((response) =>
if (response.data && response.data.data && response.data.data.token)
localStorage.setItem("user", JSON.stringify(response.data));
return response.data;
)
.catch((err) =>
console.log("An error occured: ", err);
);
;
const logout = () =>
localStorage.removeItem("user");
;
auth.js
import
REGISTER_SUCCESS,
REGISTER_FAIL,
LOGIN_SUCCESS,
LOGIN_FAIL,
LOGOUT,
SET_MESSAGE,
from "./types";
import AuthService from "../services/auth.service";
export const register = (username, email, password) => (dispatch) =>
return AuthService.register(username, email, password).then(
(response) =>
dispatch(
type: REGISTER_SUCCESS,
);
dispatch(
type: SET_MESSAGE,
payload: response.data.message,
);
return Promise.resolve();
,
(error) =>
const message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
dispatch(
type: REGISTER_FAIL,
);
dispatch(
type: SET_MESSAGE,
payload: message,
);
return Promise.reject();
);
;
export const login = (username, password) => (dispatch) =>
return AuthService.login(username, password).then(
(data) =>
dispatch(
type: LOGIN_SUCCESS,
payload: user: data ,
);
return Promise.resolve();
,
(error) =>
const message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
dispatch(
type: LOGIN_FAIL,
);
dispatch(
type: SET_MESSAGE,
payload: message,
);
return Promise.reject();
);
;
export const logout = () => (dispatch) =>
AuthService.logout();
dispatch(
type: LOGOUT,
);
;
Login.js
import React, useState, useRef from "react";
import useDispatch, useSelector from "react-redux";
import Redirect from 'react-router-dom';
import Form from "react-validation/build/form";
import Input from "react-validation/build/input";
import CheckButton from "react-validation/build/button";
import login from "../actions/auth";
const required = (value) =>
if (!value)
return (
<div className="alert alert-danger" role="alert">
This field is required!
</div>
);
;
const Login = (props) =>
const form = useRef();
const checkBtn = useRef();
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [loading, setLoading] = useState(false);
const isLoggedIn = useSelector(state => state.auth);
const message = useSelector(state => state.message);
const dispatch = useDispatch();
const onChangeUsername = (e) =>
const username = e.target.value;
setUsername(username);
;
const onChangePassword = (e) =>
const password = e.target.value;
setPassword(password);
;
const handleLogin = (e) =>
e.preventDefault();
setLoading(true);
form.current.validateAll();
if (checkBtn.current.context._errors.length === 0)
dispatch(login(username, password))
.then(() =>
// props.history.push("/home");
// window.location.reload();
)
.catch(() =>
setLoading(false);
);
else
setLoading(false);
;
if (isLoggedIn)
return <Redirect to="/profile" />;
return (
<div className="col-md-12">
<div className="card card-container">
<img
src="//ssl.gstatic.com/accounts/ui/avatar_2x.png"
className="profile-img-card"
/>
<Form onSubmit=handleLogin ref=form>
<div className="form-group">
<label htmlFor="username">Username</label>
<Input
type="email"
className="form-control"
name="email"
value=username
onChange=onChangeUsername
validations=[required]
/>
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<Input
type="password"
className="form-control"
name="password"
value=password
onChange=onChangePassword
validations=[required]
/>
</div>
<div className="form-group">
<button className="btn btn-primary btn-block" disabled=loading>
loading && (
<span className="spinner-border spinner-border-sm"></span>
)
<span>Login</span>
</button>
</div>
message && (
<div className="form-group">
<div className="alert alert-danger" role="alert">
message
</div>
</div>
)
<CheckButton style= display: "none" ref=checkBtn />
</Form>
</div>
</div>
);
;
export default Login;
Profile.js
import React from "react";
import Redirect from 'react-router-dom';
import useSelector from "react-redux";
const Profile = () =>
const user: currentUser = useSelector((state) => state.auth);
if (!currentUser)
return <Redirect to="/login" />;
return (
<div className="container">
<header className="jumbotron">
<h3>
<strong>currentUser.data.userInfo.name's</strong> Profile
</h3>
</header>
<p>
<strong>Id:</strong> currentUser.data.userInfo.userId
</p>
<p>
<strong>Token:</strong> currentUser.data.token
</p>
<p>
<strong>Email:</strong> currentUser.data.userInfo.email
</p>
<p>
<strong>Name:</strong> currentUser.data.userInfo.name
</p>
</div>
);
;
export default Profile;
【问题讨论】:
【参考方案1】:你有一些条件检查应该为你捕捉东西,但它们并不完全正确。你需要改善你的条件。
我看不到您的 Redux 状态,但我可以从错误中向后推断。您对TypeError: cannot read property 'userInfo' of undefined
的屏幕截图显示currentUser.data
是undefined
在Profile
组件中。所以这个检查:
if (!currentUser)
return <Redirect to="/login" />;
这还不够,因为您有时拥有currentUser
而没有currentUser.data
。事实上,您使用的所有属性都是 currentUser.data
的子属性,因此您可以最大限度地减少从 Redux 中选择的数据量(这有助于防止不必要的重新渲染)。
const Profile = () =>
const userData = useSelector(state => state.auth.user.data);
if (!userData)
return <Redirect to="/login" />;
return (
<div className="container">
<header className="jumbotron">
<h3>
<strong>userData.userInfo.name's</strong> Profile
</h3>
</header>
<p>
<strong>Id:</strong> userData.userInfo.userId
</p>
<p>
<strong>Token:</strong> userData.token
</p>
<p>
<strong>Email:</strong> userData.userInfo.email
</p>
<p>
<strong>Name:</strong> userData.userInfo.name
</p>
</div>
);
;
但我们不应该首先被重定向到Profile
,所以让我们看看为什么会发生这种情况。
const isLoggedIn = useSelector(state => state.auth);
if (isLoggedIn)
return <Redirect to="/profile" />;
state.auth.isLoggedIn
属性可靠吗?你需要弄清楚为什么它会评估为true
。
与此同时,我们可以检查是否存在我们在 Profile
中查找的相同用户数据。
const isLoggedIn = useSelector(state => !! state.auth.user.data);
【讨论】:
以上是关于无法读取未定义的 reactjs JWT 身份验证的属性“令牌”的主要内容,如果未能解决你的问题,请参考以下文章
如何在刷新页面上存储在本地存储中的 reactjs 中使用 JWT 进行身份验证?
无法读取未定义的属性“电子邮件”; firebase 身份验证();使用 Vuex