首页 > 解决方案 > 访问 this.state 后如何确保 setState 调用已经执行?

问题描述

我有一个注册表。当我单击“注册”按钮时,所有TextInputs内容都已验证,并且对于每个字段,我都会调用一个函数,我在其中调用 eg this.setState({usernameError: 'This field is required'})。因此,对于每个文本字段,我都有一个函数来设置该字段的错误状态。在我按下注册按钮后,我想验证所有字段,然后如果状态中有任何字段错误,则返回函数(如果所有字段都没有正确填写,用户可能无法注册)。问题是:因为setState是异步的,所以当我检查它们时,不能保证所有字段错误都已经正确设置。

2个重要注释:

  1. 我知道 setState 的第二个参数(回调),但我无法在此回调中执行条件(检查状态中的字段错误),因为 setState 调用位于它们自己的函数中
  2. 它们位于自己的函数中,因为我想重用逻辑(我也在validate<FieldName>其他地方调用函数,例如当onChangeText事件发生时)

所以我的问题是:如何确保在检查其值而不放弃我可重用的“验证器函数”时状态已经更新?

一些代码使其更清晰:

state = { usernameError: '', firstNameError: '', lastNameError: '' };

setUsernameError = () => { // This function is also called elsewhere than in handlePressRegister
    const { username } = this.state;
    if (username === '')
        this.setState({ usernameError: 'Required field' });
    else if (username.length < 2)
        this.setState({ usernameError: 'Minimum 2 characters' });
    else
        this.setState({ usernameError: undefined });
}

setFirstNameError = () => { // This function is also called elsewhere than in handlePressRegister
    ...shortened for brevity...
}

setLastNameError = () => { // This function is also called elsewhere than in handlePressRegister
    ...shortened for brevity...
}

handlePressRegister = () => {
    const { usernameError, firstNameError, lastNameError } = this.state;

    this.setUsernameError();
    this.setFirstNameError();
    this.setLastNameError();

    if (usernameError || firstNameError || lastNameError) // The errors may not be set in the state yet
        return;

我希望你能正确理解我的问题。

标签: javascriptreactjsreact-nativestatesetstate

解决方案


如果你promisify setState,你可以从每个验证器调用中返回它并调用Promise.all它:

setUsernameError = () => { // This function is also called elsewhere than in handlePressRegister
    const { username } = this.state;
    if (username === '')
        return setStatePromisified({ usernameError: 'Required field' });
    // ...
Promise.all([
    this.setUsernameError(),
    this.setFirstNameError(),
    this.setLastNameError(),
])
    .then(() => {
        // state will be updated now
        const { usernameError, firstNameError, lastNameError } = this.state;
        if (usernameError || firstNameError || lastNameError) {
            return;
        }
        // submit?
    });

另一种选择是将另一个属性添加到状态中,例如,validating在按下注册按钮时设置。下一个渲染,检测它在 a 中的变化componentDidUpdate, reset validating,并根据需要继续执行逻辑(如果没有错误,提交表单?)。


推荐阅读