在React中完成异步函数执行后调用函数

我对React很陌生,并试图通过制作小型,简单的应用程序来学习。我正在制作一个具有React功能的简单Login应用程序。我也在使用Redux storeRedux-saga。我的登录流程是:

  1. 有一个Login组件,它从用户那里提取emailpassword,并在单击登录按钮时进行POST调用。
  2. emailpassword发送到服务器,如果它们有效,则服务器将在响应中返回一个令牌,并将其保存在local storage中。
  3. 如果收到令牌,则将触发Login success的操作。在这里,我设置了一个名为success: true的标志。
  4. 在前端,我检查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_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,error: action.error
            }
        default: return state;
    }
}
export default loginReducer;

登录组件中的语句this.props.login(data)调度该操作,然后调用POST。我想等待上面提到的整个流程完成,然后再检查成功标志的值,但这不会发生。

在登录的情况下,如何在我的前端检查success标志之前等到我的登录减少器的操作完成?我阅读了async/await上的文档,但是我不太了解如何正确使用它们。有人可以帮我吗

jing35711 回答:在React中完成异步函数执行后调用函数

在进行异步调用时,您无法立即检查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'
 });
本文链接:https://www.f2er.com/3126020.html

大家都在问