在模糊和单击按钮时反应验证

React validation on blur and on button click

我有多步表单,我想进行必要的输入。验证应处于模糊状态并单击“下一步”按钮。 On blur 按预期工作,但我在验证按钮单击时遇到问题。像下面这样,不管填不填,我都不进行下一步,不知道怎么解决。

在一个文件中我有:

import React, { Component } from 'react';
import PersonalDetails from './PersonalDetails';
import CourseDetails from './CourseDetails';

class Form extends Component {
  state = {
    step: 1,
    firstname: '',
    lastname: '',
    isError: {
      firstName: true,
      lastName: true
    },
    errorMessage: {
      firstName: '',
      lastName: ''
    }

  };

  nextStep = () => {
    const { step } = this.state;
    this.setState({
      step: step + 1
    })
  }
  
  handleChange = input => e => {
    this.setState({
      [input]: e.target.value
    })

    if (input === 'firstname') {
      if (this.state.firstname.length >= 1) {
        this.setState({
          isError: {...this.state.isError, firstName: false}
        })
      }
    }

    else if (input === 'lastname') {
      if (this.state.lastname.length >= 1) {
        this.setState({
          isError: {...this.state.isError, lastName: false}
        })
      }
    }
  }

  validateFirstName = () => {
    if (this.state.firstname.length < 2) {
      this.setState({
        errorMessage: {...this.state.errorMessage, firstName: 'Type your first name (at least 2 characters)'},
        isError: {...this.state.isError, firstName: true}
      });
    }
  }

  validateLastName = () => {
    if (this.state.lastname.length < 2) {
      this.setState({
        errorMessage: {...this.state.errorMessage, lastName: 'Type your last name (at least 2 characters)'},
        isError: {...this.state.isError, lastName: true}
      });
    }
  } 

  render() {
    const {
      step,
      firstname,
      lastname,
      errorMessage,
      isError
    } = this.state;
    
    switch(step) {
      case 1: 
        return (
          <PersonalDetails 
            nextStep={this.nextStep}
            handleChange={this.handleChange}
            firstname={firstname}
            lastname={lastname}
            validateFirstName={this.validateFirstName}
            validateLastName={this.validateLastName}
            errorMessage={errorMessage}
            isError={isError}
          />
        )
      case 2:
        return (
          <CourseDetails />
        )

      default: return null
    }
  }
}

export default Form;

在其他文件中:

class PersonalDetails extends Component {
  continue = e => {
    e.preventDefault(); 
    this.props.validateFirstName();
    this.props.validateLastName();
    if (!this.props.isError.firstName && !this.props.isError.lastName) {
      this.props.nextStep();
    }
  }

  render() {
    const { 
      firstname, 
      lastname, 
      handleChange, 
      validateFirstName,
      validateLastName,
      errorMessage,
      isError
    } = this.props;

    return (
      <div>
        <form>
          <div>
            <div>
              <label htmlFor='first name'>
              First name
              </label>
              <input type='text' value={firstname} name='first name' onChange={handleChange('firstname')} onBlur={validateFirstName} />
              <p>{isError.firstName && errorMessage.firstName}</p>
            </div>

            <div>
              <label htmlFor='last name'>
              Last name
              </label>
              <input type='text' value={lastname} name='last name' onChange={handleChange('lastname')} onBlur={validateLastName} />
              <p>{isError.lastName && errorMessage.lastName}</p>
            </div>
            
          <div>
            <button onClick={this.continue}>Next</button>
          </div>

        </form>
      </div>
    )
  }
}

export default PersonalDetails;

CourseDetails 让我们假设它现在是空白页面:

class CourseDetails extends Component {

  render() {

    return (
      <div>
 
      </div>
    )
  }
}

export default CourseDetails;

由于 React 状态更新是异步的(它们不会立即应用),因此道具不会在您执行验证后立即更改。最简单的方法是 return 验证器的验证结果,如下所示:

validateFirstName = () => {
  if (this.state.firstname.length < 2) {
    this.setState({
      errorMessage: {...this.state.errorMessage, firstName: 'Type your first name (at least 2 characters)'},
      isError: {...this.state.isError, firstName: true}
    });
    return false;
  }
  return true;
}

validateLastName = () => {
  if (this.state.lastname.length < 2) {
    this.setState({
      errorMessage: {...this.state.errorMessage, lastName: 'Type your last name (at least 2 characters)'},
      isError: {...this.state.isError, lastName: true}
    });
    return false;
  }
  return true;
} 

然后你可以用它来决定你是否应该继续下一步:

continue = e => {
  e.preventDefault(); 
  const isFirstNameValid = this.props.validateFirstName();
  const isLastNameValid = this.props.validateLastName();
  if (isFirstNameValid && isLastNameValid) {
    this.props.nextStep();
  }
}

我会尝试不同的方法。我不会调用验证函数,然后立即尝试检查错误,而是提取验证本身,并将其用于单一职责。查看您当前的代码:

continue = e => {
    e.preventDefault(); 
    this.props.validateFirstName(); // You set / clear the errors in Form state
    this.props.validateLastName(); // You set / clear the errors in Form state
    if (!this.props.isError.firstName && !this.props.isError.lastName) { // You expect to have that exact state which you've just updated in 2 lines above
      this.props.nextStep();
    }
  }

this.props.isError 不会立即在您的函数中更新,您刚刚在其中调用了另外 2 个更新它的函数。在第二次调用该函数时会很明显。

让我们尝试这样切换:

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

    if (firstname.length < 2 || lastname.length < 2) {
      this.props.validateFirstName();
      this.props.validateLastName();
    } else {
      this.props.nextStep();
    }
  }

这种方法还需要您添加 firstnamelastname 道具。