如何防止重复表单验证代码

时间:2018-05-24 11:56:57

标签: forms reactjs validation jsx

我为多个输入创建了表单,其中特定输入数据应在数据输入时进行验证,并在表单提交到后端之前再次对所有数据进行验证。
要提交的条件:所有字段都是必填字段,数据有效。

我的程序有效,但我不喜欢我在2个地方重复验证码:ErrorOutput和hadleSubmit。
在ErrorOutput中,我检查数据,如有必要,显示错误消息 在handleSubmit中,我只检查数据而不显示错误消息,如果所有数据都有效,我确认提交。

如何改进我的示例以防止重复此代码,但数据验证也是在数据输入时和提交之前?

{{1}}

2 个答案:

答案 0 :(得分:2)

您可以提取FormItem组件:

class FormItem extends React.Component {
  render() {
    return (
      <div>
        <label>
          {this.props.label}
        </label>
        <input
          {...this.props.input}
        />
        <ErrorOutput 
          case={this.props.input.value} 
          name={this.props.input.name} 
          submit={this.props.onSubmit} 
        />
      </div>
    );
  }
}

并在App

中使用它
render() {
    return (
      <form onSubmit={this.handleSubmit.bind(this)}>
        <FormItem label='First name:' input={{
          type: 'text'
            name: 'firstName'
            value: this.state.firstName,
            onChange: this.handleValidation.bind(this)
          }} 
          onSubmit={this.state.submit}
        />
        <FormItem label='Phone number:' input={{
          type:'tel'
            name :'telNo'
            value : {this.state.telNo}
            onChange : {this.handleValidation.bind(this)}
          }} 
          onSubmit={this.state.submit}
        />
        <button>
          Submit
        </button> 
      </form>
    )
  }

这就是像react-final-formredux-form这样的图书馆变得方便的地方。

UPD

ErrorOutput组件不应该验证任何内容,它不是组件的责任。相反,您可以在输入模糊事件和提交之前验证您的值:

class App extends React.Component {
  constructor(props){
    super(props)

    this.state = {
      firstName: '',
      telNo: '',
      submit: false,
      errors: {},
      invalid: false,
    }
  }

  handleSubmit(e){
    e.preventDefault()
    if (this.validate()) {
      // handle error
    } else {
      // submit
    }
  }

  validate = () => {
    const { firstName, telNo } = this.state
    const errors = {}
    let invalid = false;
    if (firstName === '' || !firstName.match(/^[a-zA-Z]+$/)) {
      errors.firstName = 'first name is required'
      invalid = true;
    } else if (telNo === '' || !telNo.match(/^[0-9]+$/)) {
      telNo.telNo = 'telNo is required'
      invalid = true;
    }
    this.setState({
      invalid,
      errors,
    })
    return invalid;
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit.bind(this)}>
        <FormItem label='First name:' input={{
            type: 'text',
            name: 'firstName',
            value: this.state.firstName,
            onChange: e => this.setState({ firstName: e.target.value }),
            onBlur: () => this.validate(),
          }} 
        />
        <FormItem label='Phone number:' input={{
            type: 'tel',
            name: 'telNo',
            value: this.state.telNo,
            onChange: e => this.setState({ telNo: e.target.value }),
            onBlur: () => this.validate(),
          }} 
        />
        <button>
          Submit
        </button> 
      </form>
    )
  }
}

和FormItem和ErrorOutput:

const ErrorOutput = ({ error }) => <span>{error}</span>

class FormItem extends React.Component {
  render() {
    return (
      <div>
        <label>
          {this.props.label}
        </label>
        <input
          {...this.props.input}
        />
        {this.props.error && <ErrorOutput error={this.props.error} />}
      </div>
    );
  }
}

答案 1 :(得分:2)

const ErrorOutput = ({ errorText }) => <span>{errorText}</span>;

class App extends React.Component {
constructor(props) {
    super(props);

    this.state = {
    firstName: "",
    telNo: "",
    submit: false,
    errors: {} //Add errors object to the state.
    };
}

handleSubmit(e) {
    e.preventDefault();
    const errors = this.validateData();

    if (Object.keys(errors).length === 0) {
       alert("Success");
    }
    //else errors exist
    this.setState({ errors });
}

validateData = () => {
    let errors = {};
    const { firstName, telNo } = this.state; // read the values to validate

    if (firstName.length === 0) {
    errors.firstName = "Required";
    } else if (firstName.length > 0 && !firstName.match(/^[a-zA-Z]+$/)) {
    errors.firstName = "Letters only";
    }

    if (telNo.length === 0) {
    errors.telNo = "Required";
    } else if (telNo.length > 0 && !telNo.match(/^[0-9]+$/)) {
    errors.telNo = "Numbers only";
    }

    return errors;
};

handleValidation(e) {
    this.setState({
    [e.target.name]: e.target.value
    });
}

render() {
    const { errors } = this.state; // read errors from the state
    return (
    <form onSubmit={this.handleSubmit.bind(this)}>
        <div>
        <label>First name:</label>
        <input
            type="text"
            name="firstName"
            value={this.state.firstName}
            onChange={this.handleValidation.bind(this)}
        />
        {errors.firstName && <ErrorOutput errorText={errors.firstName} />}
        </div>
        <div>
        <label>Phone number:</label>
        <input
            type="tel"
            name="telNo"
            value={this.state.telNo}
            onChange={this.handleValidation.bind(this)}
        />
        {errors.telNo && <ErrorOutput errorText={errors.telNo} />}
        </div>
        <button>Submit</button>
    </form>
    );
}
}

render(<App />, document.getElementById("root"));