简体   繁体   中英

reactjs async / await doesn't work in first run

I have a react app, I am trying to perform login using redux and PHP.

I have a component, the component contains a form. the user enters the password and email to the form. after submitting the form the data enter an async-await function called handleSubmit . That function has another function called onSubmitLogin in the await.

from the onSubmit this goes to the actiOn creator in ajax.js file. the next step is the API PHP code, in there the PHP function checks if the user exists. now from there to the reducer and back to function via mapStateToProps ,

I want the states notActiveUserError and UserDoesNotExist to change depending on the props ( this.props.auth ) value I receive from the reducer using the checkUserValidation function.

The problem I have is that the props change but the state is not changing on the first run, every other time it works amazing but it never works on the first time after page loads.

Any help would be great.

this is the code I have: handleSubmit is in LoginForm.js (full component is at the bottom of the question)

handleSubmit = async (event) => { 
    await this.onSubmitLogin(event);
    this.checkUserValidation();
}

onSubmitLogin is in LoginForm.js (full component is at the bottom of the question)

onSubmitLogin(event){
    event.preventDefault();

    if(this.clientValidate()){
        this.clientValidate();
    }else{
        let userData ={
            email: this.state.email,
            password: this.state.password
        }
        this.props.userLogin(userData);
    }
}

the action creator

export const userLogin = (userData) => {
    return (dispatch) => {
        axios({
                url: `${API_PATH}/users/Login.php`,
                method: 'post',
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json'
                },
                data: JSON.stringify(userData)
            })
            .then(function(response) {
                dispatch({ type: USER_LOGIN, value: response.data });
            })
            .catch(function(error) {
                console.log(error);
            });
    }
}

LoginForm component:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Redirect, Link  } from 'react-router-dom';
import {
    Button,
    Form,
    FormGroup,
    FormControl,
    Col,
    Alert,
    Grid,
    Row
} from 'react-bootstrap';

import { userLogedIn } from '../../actions'; 
import { userLogin } from '../../actions/ajax'; 


class LoginForm extends Component {
    constructor() {
        super();
        this.state={
            email: '',
            username: '',
            password: '',
            auth: false,
            usernameError: '',
            passwordError: '',
            EmptyUsernameError: '',
            EmptyPasswordError: '',
            notActiveUserError: '',
            UserDoesNotExist: '',
            userid: ''
        }
        this.handleSubmit = this.handleSubmit.bind(this);
        this.onChange = this.onChange.bind(this);

    }


    clientValidate = () => {
        let isError = false;

        if(this.state.email === ''){

            this.setState({EmptyUsernameError: 'לא הזנתם דואר אלקטרוני'});
        }
        if(this.state.password === ''){
            isError = true;
            this.setState({EmptyPasswordError: 'לא הזנתם סיסמה'});
        }      
        return isError;
    }

    checkUserValidation(){
        if(this.props.auth === false && this.props.userid !== undefined){
            console.log('this.props 1', this.props);
            this.setState({notActiveUserError: 'חשבון לא מאומת'});
        }
        if(this.props.auth === false && this.props.userid === undefined){
            console.log('this.props 2', this.props);
            this.setState({UserDoesNotExist: 'משתשמ לא קיים'});
        }
    }

    onSubmitLogin(event){
        event.preventDefault();

        if(this.clientValidate()){
            this.clientValidate();
        }else{
            let userData ={
                email: this.state.email,
                password: this.state.password
            }
            this.props.userLogin(userData);
        }
    }

    handleSubmit = async (event) => { 
        await this.onSubmitLogin(event);
        this.checkUserValidation();
    }


    redirectUser = () => {    
        if(this.props.auth === true && this.props.userid != null){
            const timestamp = new Date().getTime(); // current time
            const exp = timestamp + (60 * 60 * 24 * 1000 * 7)                // add one week

            let auth = `auth=${this.props.auth};expires=${exp}`;
            let userid = `userid=${this.props.userid};expires=${exp}`;

            document.cookie = auth;
            document.cookie = userid;

            return <Redirect to='/records/biblist' />
        }
    }


    onChange(event){
        this.setState({
            [event.target.name]: event.target.value,
            auth: false,
            usernameError: '',
            EmptyPasswordError: '',
            EmptyUsernameError: '',
            notActiveUserError: '',
            UserDoesNotExist: ''
        })


    }

    isLoggedIn = () =>{
        console.log(' this.props.auth ',  this.props.auth);

    }

    render() {
        this.isLoggedIn();
        return (

                        <Form>

                            <FormGroup  controlId="formHorizontalusername">
                                <Col xs={12} sm={5} style={TopMarginLoginBtn}>
                                <Row style={marginBottomZero}>
                                    <FormControl ref="email" name="email" type="email" onChange={this.onChange} placeholder="דואר אלקטרוני" aria-label="דואר אלקטרוני"/>
                                </Row>
                                </Col>
                                <Col xs={12} sm={4} style={TopMarginLoginBtn}>
                                <Row style={marginBottomZero}>
                                    <FormControl ref="password" name="password" type="password" onChange={this.onChange} placeholder="הקלד סיסמה" aria-label="סיסמה"/>
                                    </Row>
                                </Col>

                                <Col  xs={12} sm={3} style={TopMarginLoginBtn} >

                                    <Button onClick={this.handleSubmit} type="submit" className="full-width-btn" id="loginSubmit">התחבר</Button>
                                    {this.redirectUser()}
                                    </Col>
                                    <Col xs={12}>
                                    <Link to="/passwordrecovery">שכחתי את הסיסמה</Link>
                                </Col>
                            </FormGroup>
                            {
                                this.state.EmptyUsernameError ? 
                                <Alert bsStyle="danger"> {this.state.EmptyUsernameError} </Alert> :
                                ''
                            }
                            {
                                this.state.EmptyPasswordError ? 
                                <Alert bsStyle="danger"> {this.state.EmptyPasswordError} </Alert> :
                                ''
                            }

                            {
                                this.state.usernameError ? 
                                <Alert bsStyle="danger"> {this.state.usernameError} </Alert> :
                                ''
                            }
                             {
                                 //PROBLEM!! state updates before props
                                 this.state.notActiveUserError ? 
                                <Alert bsStyle="danger">{this.state.notActiveUserError}</Alert> :
                                ''
                            }
                            {
                                //PROBLEM!! state updates before props
                                this.state.UserDoesNotExist ? 
                                <Alert bsStyle="danger">{this.state.UserDoesNotExist} </Alert> :
                                ''
                            }

                            <Row className="show-grid">

                        </Row>
                        </Form>



        );
    }
}
const bold={
    fontWeight: 'bolder'
}
const mapDispatchToProps = dispatch => {
    return {
        userLogedIn: (params) => dispatch(userLogedIn(params))
    };
};


const mapStateToProps = state => {
    return {
        userid: state.authReducer.userid,
        auth: state.authReducer.auth,
        email: state.authReducer.email
    }
}

export default connect(mapStateToProps, {userLogedIn, userLogin})(LoginForm);

If you want to use async-await in your component then you have to move your API call to your component because when you call the action from component it doesn't return data back to your component.

if you want to use redux then I suggest you should remove async-await from your component it won't work, instead use the redux state to store success or failed state and handle that change in your component from getDerivedStateFromProps

export const userLogin = (userData) => {
    return (dispatch) => {
        dispatch({ type: USER_LOGIN_BEGIN }); // reset error/login state
        axios({
                url: `${API_PATH}/users/Login.php`,
                method: 'post',
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json'
                },
                data: JSON.stringify(userData)
            })
            .then(function(response) {
                dispatch({ type: USER_LOGIN, value: response.data });
            })
            .catch(function(error) {
                dispatch({ type: USER_LOGIN_FAILED, value: error });
            });
    }
}

in your component

onSubmitLogin(event){
    event.preventDefault();
    if(!this.clientValidate()){
        let userData ={
            email: this.state.email,
            password: this.state.password
        }
        this.props.userLogin(userData);
    }
}

handleSubmit = (event) => { 
    this.onSubmitLogin(event);
  // this.checkUserValidation // move this logic to reducer and set error there according to response
}

static getDerivedStateFromProps(nextProps, prevState) {
  // handle success/error according to your need and return update state
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM