简体   繁体   English

传播运算符setState-React

[英]Spread operator, setState - React

I have a state with validations like this: 我有这样的验证状态:

this.state = {
        email: '', pass: '',
        errors: {
            email: '', pass: ''
        }
    }

and when a user press a button, it validates the form like this: 当用户按下按钮时,它将验证如下形式:

    onSubmit = (e) => {
    e.preventDefault();

    this.setState({errors: {pass: '', email: ''}});

    const pass = this.state.pass.trim();

    if(!isEmail(this.state.email)){
        this.setState({errors: {...this.state.errors, email: 'Invalid Email.'}});
    }

    // return; - in this way email state error will be ok

    if(pass.length < 6){
        this.setState({errors:{ ...this.state.errors, pass: 'Password Invalid'}});
    }

    return console.log(this.state);
};

I am using ... operator to append type of errors in the errors object. 我正在使用...运算符将错误类型追加到errors对象中。 The problem is that, if the email is invalid and there is an error for the password the state is like this: 问题是,如果电子邮件无效并且密码错误,则状态如下:

errors: {email: '', pass: 'Password Invalid'}

If I use return before pass check, the email error state works normal. 如果我在通过检查之前使用return ,则电子邮件错误状态正常。 I know that setState is async, but how to append different values of deep state object ? 我知道setState是异步的,但是如何附加不同深度状态对象的值呢?

Just setState after you've completely created your errors object. 完全创建错误对象后,只需setState You're setting state more than you need to. 您设置的状态超出了您的需要。 You're only really interested in setting the state in this function once you know what all the errors are. 一旦知道所有错误是什么,您才真正对在此功能中设置状态感兴趣。

onSubmit = (e) => {
    e.preventDefault();
    const pass = this.state.pass.trim();
    let errors = { pass: '', email: '' };
    if (!isEmail(this.state.email)) {
        errors.email = 'Invalid Email.';
    }
    if (pass.length < 6) {
        errors.pass = 'Password Invalid';
    }
    this.setState({ errors });
}

Using the ... operator here was not the issue. 在这里使用...运算符不是问题。 What was likely occurring was that React was bundling your updates together and so each of them was looking at the same state. 可能发生的事情是,React将您的更新捆绑在一起,因此每个更新都处于相同的状态。 So if you have the state as 因此,如果您的状态为

{
    error: {
        email: '',
        pass: '',
    }
}

and you have two updates batched together 并且您有两个更新一起批处理

setState({errors: {...this.state.errors, email: 'Invalid Email.'}});
setState({errors:{ ...this.state.errors, pass: 'Password Invalid'}});

they will both see the same state and make updates accordingly to produce the following two state updates 他们都将看到相同的状态,并进行相应的更新以产生以下两个状态更新

this.state = {
    error: {
        email: 'Invalid Email',
        pass: '',
    }
};
this.state = {
    error: {
        email: '',
        pass: 'Password Invalid',
    }
};

of which the second is most likely to be your result because it's the last one that was assigned to the state. 其中第二个最有可能是您的结果,因为它是分配给该州的最后一个。

With state function you can do it: 使用状态功能,您可以执行以下操作:

this.setState(prevState => {
   const errors = {};

    if(!isEmail(prevState.email)){
        errors.email = 'Invalid Email.';
    }

    if(prevState.pass.trim().length < 6) {
        errors.pass = 'Password Invalid'
    }

    return {errors: {...prevState.errors, ...errors}}; // combine your new errors with another keys errors if exists
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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