【问题标题】:ReactJS state is modified with delay?ReactJS 状态被延迟修改?
【发布时间】:2017-07-19 22:41:47
【问题描述】:

我正在以编程方式验证电子邮件和密码输入以进行简单登录,这里是调用其他验证电子邮件的函数的函数。

  handleLogin(event) {
    this.validateEmail();
    this.validatePassword();

    if (this.state.emailValid === 'error' || this.state.passwordValid === 'error') {
      alert('invalid form');
      return;
    };

    const email = ReactDOM.findDOMNode(this.refs.email).value;
    const password = ReactDOM.findDOMNode(this.refs.password).value;
    const creds = { email: email, password: password }
    this.props.onLoginClick(creds)
  }

请注意,首先我调用的是 validateEmail() 函数,该函数会修改指示输入是否正确的存储,这是 validateEmail() 源代码:

  validateEmail() {
    const email = ReactDOM.findDOMNode(this.refs.email).value;
    let validEmail = /^.+([.%+-_]\w+)*@\w+([.-]\w+)*\.\w+([-.]\w+)*$/.test(email);

    if (!validEmail) {
      this.setState({
        emailValid: 'error'
      });
      return;
    }
    this.setState({
      emailValid: 'success'
    });
  }

但是if语句中state.emailValid还没有更新,这是状态修改的延迟,所以alert()没有显示。如何正确获取更新状态?

谢谢

【问题讨论】:

标签: forms reactjs input


【解决方案1】:

这里要注意的是 setState 是异步的。在您的 handleLogin 方法中同步的所有其他内容完成之前,它不会更新状态。

对于 React,我喜欢尽可能多地使用状态作为单一事实来源。在上面的示例中,您将 html 元素作为事实和状态的来源。通过将组件更改为受反应状态控制,您可以在每次击键时验证表单。

表单和受控组件

首先将输入的状态保持在状态

class LoginForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      email: '',
      emailValid: true,
    };

    // we bind the function in case we want to 
    // control text in child component
    this.emailChange = this.handleEmailChange.bind(this);
  }

  emailChange(event) {
    this.setState({email: event.target.value});
  }

  render() {
    <textarea value={this.state.email} onChange={this.emailChange} /> 
  }
}

现在,每当您键入 html 输入的状态时,都会在 react 中处理。这将使您能够更轻松地检查其有效性。我们可以通过向我们的类添加另一个方法来做到这一点:

class LoginForm extends React.Component {

  // ...all the stuff from above

  validateEmail() {
    let validEmail = /^.+([.%+-_]\w+)*@\w+([.-]\w+)*\.\w+([-.]\w+)*$/.test(email);

    if (!validEmail) {
      // Object.assign just ensures immutability
      this.setState(Object.assign({}, this.state, {
        emailValid: false
      }))
    } else {
      // If using babel, this is ensure immutable also
      this.setState({
        ...state,
        emailValid: true
      })
    }
  }

  // or....

  validateEmail() {
    let validEmail = /^.+([.%+-_]\w+)*@\w+([.-]\w+)*\.\w+([-.]\w+)*$/.test(email);
    this.setState({...state, emailValid: validEmail})
  }

  // ...render method
}

现在将在每次击键时进行验证。当您需要提交表单时,您只需检查状态是否数据有效并且不需要引用 dom。您可以从状态发送数据。

【讨论】:

    猜你喜欢
    • 2021-09-20
    • 1970-01-01
    • 1970-01-01
    • 2021-01-10
    • 2018-09-20
    • 1970-01-01
    • 2015-04-15
    • 2020-11-22
    • 1970-01-01
    相关资源
    最近更新 更多