我对React很陌生,并试图通过制作小型,简单的应用程序来学习。我正在制作一个具有React
功能的简单Login
应用程序。我也在使用Redux store
和Redux-saga
。我的登录流程是:
Login
组件,它从用户那里提取email
和password
,并在单击登录按钮时进行POST
调用。email
和password
发送到服务器,如果它们有效,则服务器将在响应中返回一个令牌,并将其保存在local storage
中。Login success
的操作。在这里,我设置了一个名为success: true
的标志。success
标志的值,如果是success==true
,则重定向到另一个名为Customers
的页面登录组件
import React, { Component } from 'react';
import { connect } from "react-redux";
import { withRouter } from 'react-router-dom';
import { loginRequest } from "../../actions/loginActions";
import './styles.css';
class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: '',
error: '',
};
}
dismissError = () => {
this.setState({ error: '' });
}
handleSubmit = (evt) => {
evt.preventDefault();
let { email, password } = this.state;
if (!email) {
return this.setState({ error: 'Username is required' });
}
if (!password) {
return this.setState({ error: 'Password is required' });
}
let data = {
email: email,
password: password
}
this.props.login(data); //dispatches a method which then makes the POST call
//the checking happens before the above function has finished executing
if (this.props.success)
this.props.history.push('/customers');
else
return this.setState({
error: 'Invalid Username/Password'
});
}
handleChange = (evt) => {
this.setState({
[evt.target.name]: evt.target.value
});
}
render() {
let { email, password } = this.state;
return (
<form className="loginForm" onSubmit={this.handleSubmit}
action="/upload">
<h2>Login</h2>
{
this.state.error &&
<h3 className='error' onClick={this.dismissError}>
<button onClick={this.dismissError}>✖</button>
{this.state.error}
</h3>
}
<label className="FormFields label">Email</label>
<input type="email" className="FormFields" name="email"
value={email}
onChange={(event) => this.handleChange(event)} />
<br />
<label className="FormFields label">Password</label>
<input type="password" className="FormFields" name="password"
value={password}
onChange={(event) => this.handleChange(event)} />
<br />
<input type="submit" className="FormFields submit"
value="Login" />
</form>
);
}
}
const mapStateToProps = (state) => {
return {
loading: state.login.loading,
success: state.login.success
}
}
const mapDispatchToProps = (dispatch) => {
return { login: (data) => {dispatch(loginRequest(data))} }
}
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Login));
登录传奇
import { put, takeEvery, call } from 'redux-saga/effects'
import { LOGIN_REQUEST, LOGIN_PENDING, LOGIN_SUCCESS, LOGIN_FAILURE } from '../actions/loginActions';
export function* login(action) {
const { data } = action.payload;
yield put({ type: LOGIN_PENDING })
let url = 'myserverurl/login'
try {
const response = yield call(fetch, url, {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json',
}
});
let tokenObj = yield response.json();
if (response.status === 200) {
localStorage.setItem('user', tokenObj.token);
yield put({ type: LOGIN_SUCCESS, token: tokenObj.token })
}
}
catch (error) {
yield put({ type: LOGIN_FAILURE, error })
}
}
export function* watchLogin() {
yield takeEvery(LOGIN_REQUEST, login)
}
登录还原器非常简单。
Login Reducer
import { LOGIN_REQUEST, LOGIN_PENDING, LOGIN_SUCCESS, LOGIN_FAILURE } from '../actions/loginActions';
const initState = {
loading: false,
success: false,
error: ''
}
const loginReducer = (state = initState, action) => {
switch (action.type) {
case LOGIN_REQUEST:
return {
...state,
loading: false
}
case LOGIN_PENDING:
return {
...state,
loading: true
}
case LOGIN_SUCCESS:
return {
...state,
success: true,
loading: false
}
case LOGIN_FAILURE:
return {
...state,
loading: false,
success: false,
error: action.error
}
default: return state;
}
}
export default loginReducer;
登录组件中的语句this.props.login(data)
调度该操作,然后调用POST
。我想等待上面提到的整个流程完成,然后再检查成功标志的值,但这不会发生。
在登录的情况下,如何在我的前端检查success
标志之前等到我的登录减少器的操作完成?我阅读了async/await
上的文档,但是我不太了解如何正确使用它们。有人可以帮我吗
答案 0 :(得分:2)
在进行异步调用时,您无法立即检查this.props.success
,需要在success
中添加对getDerivedStateFromProps
道具的检查
在您的登录组件中添加getDerivedStateFromProps
static getDerivedStateFromProps(nextProps, prevState) {
if(!nextProps.loading){
if(nextProps.success === true) {
nextProps.history.push('/customers');
} else {
return { error: 'Invalid Username/Password' }
}
}
return null
}
从handleSubmit删除以下代码
if (this.props.success)
this.props.history.push('/customers');
else
return this.setState({
error: 'Invalid Username/Password'
});