如何确定状态何时完成更新?

时间:2017-10-23 13:38:42

标签: javascript reactjs

我是新来的反应,所以请耐心等待。我正在使用登录表单,此表单将在提交表单后实时验证并且错误成为现实。无论如何,默认情况下我有状态isFormValid: false的属性。

这将通过handleFormSubmission构造函数更新:

  /**
   * handleFormSubmission, submission method for user
   * account login. Dispatches the login action.
   *
   * @param  {Object} event
   */
  handleFormSubmission(event) {
    event.preventDefault();
    this.setState({
      formSubmitted: true
    },() => {
      this.validateForm();
      if (this.state.isFormValid) {
        if (this.state.userCreatingAccount) {
          this.props.createUserAccount(
            this.state.email,
            this.state.password,
            this.state.firstName,
            this.state.lastName
          )
        } else {
          this.props.login(
            this.state.email,
            this.state.password
          );
        }
      }
    });
  }

我在我的状态对象中设置formSubmitted: true,然后通过回调执行表单提交。我的问题是this.validateForm()。在setState内部this.validateForm()完成后,我需要执行代码。也许我可以宣传它? this.validateForm().then(functio.......)。这样做有问题,因为这个函数不只是一次更新状态,而是动态多次。

这是我的验证表单功能:

  /**
   * function validateForm, error handling for
   * dynamic form input fields. Resets state errors
   * on exection, then updates state via callback.
   */
  validateForm(){
    // Reset state.
    this.setState({
      isFormValid: true,
      errors: Object.assign(this.state.errors, {
        email: {},
        password: {},
        firstName: {},
        lastName: {}
      })
    }, () => {
      if (this.state.formSubmitted) {
        // Iterate over input fields, if length is 0
        // set an error via the state name.
        for (var inputField in this.state.errors) {
          if (this.state.errors.hasOwnProperty(inputField)) {
            if (inputField !== 'email') {
              if (
                !this.state.userCreatingAccount && 
                inputField !== 'firstName' && 
                inputField !== 'lastName'
              ) {
                if (this.state[inputField].length === 0) {
                  this.setState({
                    isFormValid: false,
                    errors: Object.assign(this.state.errors, {
                      [inputField]: {
                        required: true
                      }
                    })
                  });
                }
              } else {
                if (this.state[inputField].length === 0) {
                  this.setState({
                    isFormValid: false,
                    errors: Object.assign(this.state.errors, {
                      [inputField]: {
                        required: true
                      }
                    })
                  });
                }
              }
            } else {
              // Email validation.
              if (this.state[inputField].length === 0) {
                this.setState({
                  isFormValid: false,
                  errors: Object.assign(this.state.errors, {
                    [inputField]: {
                      required: true
                    }
                  })
                });
              } else if (!/^((?!.*\.\.)[a-z0-9\.\-]+[^\.]@[a-z0-9\-]+(?:\.[a-z]+)+)$/mgi.test(
                this.state[inputField]
              )) {
                this.setState({
                  isFormValid: false,
                  errors: Object.assign(this.state.errors, {
                    [inputField]: {
                      invalid: true
                    }
                  })
                });
              }
            }
          }
        }
      }
    });
  }

简而言之,此函数更新输入字段的状态。它动态地执行,意味着1,2,3,4等字段,具体取决于那些字段值。我希望this.validateForm()内部的逻辑首先完成。紧随其后的代码取决于在this.validateForm()中设置的新状态值。但是setState是异步的。

希望这个问题有道理!提前谢谢。

2 个答案:

答案 0 :(得分:2)

你的代码对我来说有点太复杂,无法提供一个有效的例子,但我想我可以给你一些你可以做的事情。

我看到的第一个问题是你有办法,太多了setState()。这本身并不坏,但管理复杂的逻辑是一个令人头疼的问题。很容易意外地出现多次重新渲染的情况,这些都是徒劳的。

这就是我要做的事情:

  1. 分解与UI的表示没有直接关系的任何状态变量。例如,似乎就像您的formSubmitted变量仅用于您的逻辑中以确定if...else结果。
    您可能需要仔细检查这一点,但如果是这种情况,请将此类变量放在组件实例中。与this.formSubmitted代替this.state.formSubmitted一样。为什么这样?它简化了您的应用程序逻辑,使您无需执行异步setState,然后在回调中继续您的逻辑...

  2. 请勿在{{1​​}}中进行任何状态更改。而是构造一个新对象,它反映了下一个渲染中所需状态的对象。在函数结束时,返回此构造对象。

  3. 您现在可以在validateForm()函数中设置状态为handleFormSubmission(),其中this.setState(obj)是您从上面的步骤2返回的对象。在obj的回调中做最后一点逻辑。如果您返回的对象包含所有需要的变量(我没有检查),您甚至可以跳过回调,只需检查setState()而不是obj

  4. TL; DR 努力在应用中的任何一个操作或流程中始终执行this.state 。这并非总是可行,但应该在99.999%的时间内完成。

    祝你好运。

答案 1 :(得分:1)

我认为您可以使用React组件生命周期。我喜欢这篇关于解释的文章:http://busypeoples.github.io/post/react-component-lifecycle/,或者你可以从这里阅读有关setState的内容:https://reactjs.org/docs/react-component.html#setstate。 我们可以使用componentDidUpdate()在组件状态更改后执行操作。这是对代码的修改:

componentDidUpdate() {
  if (this.state.isFormValid) {
   if (this.state.userCreatingAccount) {
    this.props.createUserAccount(
       this.state.email,
       this.state.password,
       this.state.firstName,
       this.state.lastName
     )
   } else {
     this.props.login(
       this.state.email,
       this.state.password
     );
   }
}

handleFormSubmission(event) {
    event.preventDefault();
    this.setState({
      formSubmitted: true
    },() => {
      this.validateForm();
      /* move them to componentDidUpdate() */
      //if (this.state.isFormValid) {
      //  if (this.state.userCreatingAccount) {
      //   this.props.createUserAccount(
      //      this.state.email,
      //      this.state.password,
      //      this.state.firstName,
      //      this.state.lastName
      //    )
      //  } else {
      //    this.props.login(
      //      this.state.email,
      //      this.state.password
      //    );
      //  }
      }
    });
}

希望这可以提供帮助。