[英]How to make Login using redux in react js
I am creating login concept using redux in react.js I am getting an error - Cannot read property 'name' of undefined in {this.props.userlogin.name} 我在react.js中使用redux创建登录概念,但出现错误-无法读取{this.props.userlogin.name}中未定义的属性'name'
I have created action and reducer in code. 我已经在代码中创建了动作和减速器。
My header.js File is - 我的header.js文件是-
import React, { Component } from "react";
import { Link, withRouter } from 'react-router-dom';
import './Header.css'
import logo from '../logo.png';
import LoadingSpinner from '../loadingspinner.component';
import Modal from 'react-bootstrap/Modal';
import { loginUser } from "../../Actions/actions";
import PropTypes from "prop-types";
import { connect } from "react-redux";
const emailRegex = RegExp(/^[a-zA-Z0-9_\-\.]+@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/)
const formValid = formErrors => {
let valid = true;
Object.values(formErrors).forEach(val => {
val.length > 0 && (valid = false)
});
return valid;
}
class Header extends Component {
constructor(props) {
super(props);
this.state = {
show: false,
email: "",
name: "",
password: "",
loading: false,
message: '',
formErrors: {
email: "",
password: ""
}
};
this.handleShow = () => {
this.setState({ show: true });
};
this.handleHide = () => {
this.setState({ show: false });
};
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
componentDidMount() {
// if (localStorage.usertoken && localStorage.usertoken != 'undefined') {
// const token = localStorage.usertoken;
// const decoded = jwt_decode(token);
// console.log(decoded);
// this.setState({
// name: decoded.name
// })
// }
}
onChange(e) {
const { name, value } = e.target;
// console.log("name :", name);
// console.log("value :", value);
this.setState({ [e.target.name]: e.target.value });
let formErrors = this.state.formErrors;
switch (name) {
case 'email':
formErrors.email = emailRegex.test(value) ? '' : "Invalid Email Address";
break;
case 'password':
formErrors.password = value.length < 6 ? 'Minimum 6 character required' : "";
break;
default: break;
}
this.setState({ formErrors, [name]: value }, () => console.log(this.state));
}
logOut(e) {
e.preventDefault();
localStorage.removeItem("usertoken");
this.props.history.push("/");
}
onSubmit(e) {
if (formValid(this.state.formErrors)) {
this.setState({
loading: true,
})
e.preventDefault();
const user = {
email: this.state.email,
password: this.state.password
};
this.props.loginUser(user).then((res, err) => {
// console.log(res);
if (res.Success == '0') {
this.setState({
loading: false,
message: res.Message
})
}
else {
// if (localStorage.usertoken && localStorage.usertoken != 'undefined') {
// const token = localStorage.usertoken;
// const decoded = jwt_decode(token);
// console.log(decoded);
// this.setState({
// name: decoded.name
// })
// }
this.handleHide();
}
});
}
else {
e.preventDefault();
console.error('FORM ERROR - DISPLAY ERROR MESSAGE');
}
}
render() {
const { loading, message } = this.state;
const { formErrors } = this.state;
const loginRegLink = (
<div className="" style={{ display: 'inline-flex' }}>
<li class="nav-item">
<a onClick={this.handleShow} class="nav-link" style={{ cursor: 'pointer' }} >Login <i class="fa fa-user" aria-hidden="true"></i></a>
</li>
{/* <li class="nav-item">
<a class="nav-link" href="/">SignUp <i class="fa fa-lock" aria-hidden="true"></i></a>
</li> */}
<li class="nav-item">
<a class="nav-link" href="/">AboutUs</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/">ContactUs</a>
</li>
</div>
);
const userLink = (
<div className="" style={{ display: 'inline-flex' }}>
<li class="nav-item">
<Link className="nav-link" to="/">{this.props.userlogin.name}</Link>
</li>
<li class="nav-item">
<a href="" onClick={this.logOut.bind(this)} className="nav-link">
Logout
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/">AboutUs</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/">ContactUs</a>
</li>
</div>
);
return (
<nav class="navbar navbar-expand-md navbar-light bg-basic" >
<Link to="/">
<img src={logo} />
</Link>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarTogglerDemo03" aria-controls="navbarTogglerDemo03" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse w-100 flex-md-column" id="navbarTogglerDemo03">
<ul class="navbar-nav ml-auto small mb-2 mb-md-0">
{/* <li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<img className="country-image" src="https://www.countryflags.io/be/shiny/64.png" /> English
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</li> */}
{localStorage.usertoken && localStorage.usertoken != 'undefined' ? userLink : loginRegLink}
</ul>
</div>
{/* model popup */}
<Modal
show={this.state.show}
onHide={this.handleHide}
dialogClassName="modal-90w"
aria-labelledby="example-custom-modal-styling-title"
centered
size="md"
>
<Modal.Header closeButton>
<Modal.Title id="example-custom-modal-styling-title text-center">
IT Referrals Login
</Modal.Title>
</Modal.Header>
<Modal.Body>
<div class="form-group" id="sampleTableForEmployee">
{message !== '' &&
<div class="alert alert-danger alert-dismissible" role="alert">
{message}
</div>
}
<form onSubmit={this.onSubmit}>
<div className="row">
<div className="col-md-12">
<div className="input-class-field">
<div className="form-group">
<label htmlFor="email"><b>Email</b></label>
<div className="input-group">
<span className="input-group-addon">
<span className="glyphicon glyphicon-envelope" />
</span>
<input
type="email"
className='form-control'
id="email"
name="email"
style={{ width: '100%' }}
placeholder="anyone@example.com"
required="required"
value={this.state.email}
onChange={this.onChange}
/>
{formErrors.email && (
<span className="errorMessage" style={{ color: 'red', fontSize: '14px' }}>{formErrors.email}</span>
)}
</div>
</div>
<div className="form-group">
<label htmlFor="password"><b>Password</b></label>
<div className="input-group">
<span className="input-group-addon">
<span className="glyphicon glyphicon-envelope" />
</span>
<input
type="password"
className={formErrors.password.length > 0 ? 'error form-control' : 'form-control'}
style={{ width: '100%' }}
id="password"
name="password"
placeholder="********"
required="required"
value={this.state.password}
onChange={this.onChange}
/>
{formErrors.password.length > 0 && (
<span className="errorMessage" style={{ color: 'red', fontSize: '14px' }}>{formErrors.password}</span>
)}
</div>
</div>
<div className="form-group">
<button
type="submit"
className="btn btn-primary btn-block pull-right"
id="btnContactUs"
>
{loading ? <LoadingSpinner /> : "Login"}
</button><br /><br />
{/* <p className="forgetpassword"><a href="">Forget my password ?</a></p> */}
{/* <p className="signup">Don't have an account? <Link to="/register"> Create Now</Link> </p> */}
</div>
</div>
</div>
</div>
</form>
</div>
<hr />
</Modal.Body>
</Modal>
{/* end modal popup */}
</nav >
)
}
}
Header.propTypes = {
loginUser: PropTypes.func.isRequired,
userlogin: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
userlogin: state.userlogin
});
export default connect(
mapStateToProps,
{ loginUser }
)(Header);
My reducer code is - 我的减速器代码是-
import { SET_CURRENT_USER } from "../Actions/actions";
export default function userlogin(state = [], action = {}) {
switch (action.type) {
case SET_CURRENT_USER:
return action.userlogin;
default:
return state;
}
}
My action code is - 我的动作代码是-
// code to login user
export const SET_CURRENT_USER = "SET_CURRENT_USER";
export function loginUser(user) {
return dispatch => {
return axios
.post("http://localhost:4000/login", {
email: user.email,
password: user.password
})
.then(res => {
// Set token to localStorage
localStorage.setItem("usertoken", res.data.token);
// Decode token to get user data
const decoded = jwt_decode(res.data.token);
// Set current user
dispatch(setCurrentUser(decoded));
})
.catch(err => {
console.log(err.response.data.msg);
});
};
}
export function setCurrentUser(userlogin) {
return {
type: SET_CURRENT_USER,
userlogin
};
}
How to resolve TypeError: Cannot read property 'name' of undefined error in header.js file.. How can we make login ? 如何解决TypeError:无法读取header.js文件中未定义错误的属性“名称”。我们如何进行登录?
i guess the problem is at here: 我猜问题出在这里:
const userLink = (
<div className="" style={{ display: 'inline-flex' }}>
<li class="nav-item">
// here, because when render this const will run once and try to find the userLogin.name, but because u haven't login, it doesn't exist
<Link className="nav-link" to="/">{this.props.userlogin.name}</Link>
</li>
<li class="nav-item">
<a href="" onClick={this.logOut.bind(this)} className="nav-link">
Logout
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/">AboutUs</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/">ContactUs</a>
</li>
</div>
);
Try to create by function 尝试按功能创建
const userLink = () => (
<div className="" style={{ display: 'inline-flex' }}>
<li class="nav-item">
<Link className="nav-link" to="/">{this.props.userlogin.name}</Link>
</li>
<li class="nav-item">
<a href="" onClick={this.logOut.bind(this)} className="nav-link">
Logout
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/">AboutUs</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/">ContactUs</a>
</li>
</div>
);
and use it like 并像这样使用
{localStorage.usertoken && localStorage.usertoken != 'undefined' ? userLink() : loginRegLink}
hope this will work 希望这会工作
Based on your code I would expect state.userlogin
to start off as an empty array. 根据您的代码,我希望
state.userlogin
从一个空数组开始。 Since you are setting your reducer to have an initial state of empty array: 由于您将减速器设置为具有空数组的初始状态:
export default function userlogin(state = [], action = {}) {}
And you link userlogin
from your store to your component in here: 您
userlogin
将商店中的用户userlogin
链接到此处的组件:
const mapStateToProps = state => ({
userlogin: state.userlogin
});
However userlogin
seems to be undefined instead, which makes me believe you haven't mapped your reducer inside your rootreducer correctly. 但是,
userlogin
似乎是未定义的,这使我相信您尚未在rootreducer内正确映射reducer。 (perhaps you used camelcase there?) (也许您在那儿使用过驼峰箱?)
If you have, then perhaps the correct store is not provided to your app or you may have changed the state of userlogin
to undefined
after initialisation. 如果已注册,则可能未将正确的存储提供给您的应用程序,或者您可能已在初始化后将用户
userlogin
状态更改为undefined
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.