Как предотвратить повторение кода проверки формы - PullRequest
0 голосов
/ 24 мая 2018

Я создал форму для нескольких входов, где конкретные входные данные должны быть проверены во время ввода данных и еще раз для всех данных непосредственно перед отправкой формы на сервер.
Условия для отправки:все поля являются обязательными, и данные действительны.

Моя программа работает, но мне не нравится, что я повторяю код проверки в 2 местах: в ErrorOutput и hadleSubmit.
В ErrorOutput я проверяюданные и, если необходимо, отобразить сообщение об ошибке.
В handleSubmit я просто проверяю данные без отображения сообщения об ошибке и, если все данные действительны, я подтверждаю отправку.

Как мне улучшить мой пример, чтобы предотвратить повторение этого кода, но проверка данных была также во время ввода данных и перед отправкой?

import React from 'react'
import { render } from 'react-dom'

const ErrorOutput = props => {
  let name = props.name
  let inputValue = props.case
  let submit = props.submit
  // Data validation
  if (name === 'firstName') {
    if (!inputValue.match(/^[a-zA-Z]+$/) && inputValue.length > 0) {
        return <span>Letters only</span>
      } else if (submit && inputValue.length === 0) {
        return <span>Required</span>
      }
    return <span></span>
  }
  if (name === 'telNo') {
    if(!inputValue.match(/^[0-9]+$/) && inputValue.length > 0) {
        return <span>Numbers only</span>
      } else if (submit && inputValue.length === 0) {
        return <span>Required</span>
      }
    return <span></span>
  }
}

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

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

  handleSubmit(e){
    e.preventDefault()
    let submit = true
    let error = true
    const { firstName, telNo } = this.state
    this.setState ({submit: submit})

    // Repeat the data validation before submission
    if (firstName === '' || !firstName.match(/^[a-zA-Z]+$/)) {
      error = true
    } else if (telNo === '' || !telNo.match(/^[0-9]+$/)) {
      error = true
    } else {
      error = false
    }

    // Submited if all data is valid
    if (!error) {
      // send data
      return alert('Success!')
    }
  }

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

  render() {
    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)}
          />
          <ErrorOutput case={this.state.firstName} name={'firstName'} submit = {this.state.submit} />
        </div>
        <div>
          <label>
            Phone number:
          </label>
          <input
            type='tel'
            name ='telNo'
            value = {this.state.telNo}
            onChange = {this.handleValidation.bind(this)}
          />
          <ErrorOutput case={this.state.telNo} name={'telNo'} submit = {this.state.submit} />
        </div>
        <button>
          Submit
        </button> 
      </form>
    )
  }
}

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

Ответы [ 2 ]

0 голосов
/ 24 мая 2018
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"));
0 голосов
/ 24 мая 2018

Вы можете извлечь 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>
    )
  }

, здесь библиотеки, такие как реакция-окончательная форма и избыточная форма становятся удобными.

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>
    );
  }
}
...