Как сделать проверку формы в реакции? - PullRequest
1 голос
/ 29 февраля 2020

Я создал форму реакции. Мне нужна помощь в проверке формы. Я создал пользовательские проверки.

Как видно из кода, у меня есть 2 поля электронной почты в одной форме. Если я пытаюсь ввести адрес электронной почты в одном поле, ошибка отображается для обоих полей электронной почты. Причиной этого является использование того же самого свойства свойства invalidEmail. Я не хочу создавать отдельное свойство состояния для каждого поля. Тот же случай с полями возраста и телефона.

Может кто-нибудь помочь мне решить эту проблему. Вы можете предложить мне разные подходы, если у вас есть. Я не хочу добавлять библиотеки или плагины для проверок.

Ссылка Codesandbox: https://codesandbox.io/s/heuristic-bartik-1lucn

Ответы [ 3 ]

3 голосов
/ 29 февраля 2020

Примечание: Вы можете смоделировать эту логику c для разработки, написания более качественной и лучшей практики для всех областей: электронная почта, возраст, телефон, ... в вашем проекте реагирования

Вы можете попробовать это и отредактировать свои коды и поля:

Добавить новое состояние: invalidFields для хранения недопустимых полей:

state = {
    user: {
      name: "",
      email1: "",
      email2: "",
      age: "",
      city: "",
      phone: ""
    },
    invalidNumber: false,
    invalidEmail: false,
    invalidFields: [], // Add this line
    submitted: false
  };

, а затем отредактировать свои условия в handleChange function :

добавить имя к this.validateEmail(value, name);

if (name === "email1") {
  this.validateEmail(value, name); // add name
}
if (name === "email2") {
  this.validateEmail(value, name); // add name
}
if(name === "age") {
  this.validateNumber(value, name); // add name
}
if(name === "phone") {
  this.validateNumber(value, name); // add name
}

, а затем изменить validateEmail function: Отредактировано

validateEmail = (value, name) => {
    const regex = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
    if (value && !regex.test(value)) {
      // add invalidFields to this.setState 
      this.setState({ invalidEmail: true, invalidFields: [...this.state.invalidFields, name] });
    } else {
      // add invalidFields to this.setState and then filter
      this.setState({ invalidEmail: false, invalidFields: this.state.invalidFields.filter(item => item !== name) });
    }
  };

и, наконец, изменить условие для ошибки показа: Отредактировано

// email1
{submitted && this.state.invalidFields.includes('email1') && (
    <div style={{ color: "red" }}>Email is invalid</div>
)}

// email2
{submitted && this.state.invalidFields.includes('email2') && (
    <div style={{ color: "red" }}>Email is invalid</div>
 )}
1 голос
/ 29 февраля 2020

Добавить новую переменную в состояние, которая отслеживает, являются ли обязательные поля действительными. Используйте эту переменную для отключения / включения кнопки отправки.

state = {
 ...
  isValidForm: false
}

validateNumber = value => {
  const regex = /^[0-9]\d*$/;
  return regex.test(value);
};

validateEmail = email => {
  /* eslint-disable-next-line */
  const regexp = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
  return regexp.test(email);
};

handleChange = e => {
  const { name, value } = e.target;
  const { user } = this.state;

  this.setState(
    {
      user: {
        ...user,
        [name]: value
      }
    },
    () => {
      // update the value here
      this.setState({
        isValidForm:
          this.validateEmail(this.state.user.email1) &&
          this.validateEmail(this.state.user.email2) &&
          this.validateNumber(this.state.user.age) &&
          this.validateNumber(this.state.user.phone)
      });
    }
  );
};

Затем отключите / включите кнопку отправки на основе введенных значений.

<button disabled={!this.state.isValidForm} type="submit">
  Submit
</button>

Чтобы отобразить ошибки во время ввода текста, добавьте переменная в состоянии, в которой хранятся прикосновенные входы, вход onFocus добавляет сфокусированное имя входа в массив.

state = {
 ...
 isTouched: []
}

<div>
  <label htmlFor="email2">Email 2</label>
  <input
    type="email"
    id="email2"
    name="email2"
    onFocus={() => this.isTouched("email2")}
    value={user.email2}
    onChange={this.handleChange}
  />
  {submitted && !user.email2 && (
    <div style={{ color: "red" }}>Email 2 is required</div>
  )}
  {!this.validateEmail(this.state.user.email2) &&
    this.state.isTouched.includes("email2") && (
      <div style={{ color: "red" }}>Email is invalid</div>
    )}
</div>

.App {
  font-family: sans-serif;
  text-align: center;
}

div {
  margin: 0 0 10px 0;
  clear: both;
  overflow: hidden;
}
div label {
  float: left;
  width: 100px;
  text-align: left;
}
div input,
div select {
  float: left;
  width: 200px;
  padding: 5px;
  clear: both;
}
div div {
  text-align: left;
}
button {
  float: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
<div id="root"></div>

<script type="text/babel">

class App extends React.Component {
  state = {
    user: {
      name: "",
      email1: "",
      email2: "",
      age: "",
      city: "",
      phone: ""
    },
    invalidNumber: false,
    invalidEmail: false,
    submitted: false,
    isValidForm: false,
    isTouched: []
  };

  validateNumber = value => {
    const regex = /^[0-9]\d*$/;
    return regex.test(value);
  };

  validateEmail = email => {
    /* eslint-disable-next-line */
    const regexp = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
    return regexp.test(email);
  };

  handleChange = e => {
    const { name, value } = e.target;
    const { user } = this.state;

    this.setState(
      {
        user: {
          ...user,
          [name]: value
        }
      },
      () => {
        this.setState({
          isValidForm:
            this.validateEmail(this.state.user.email1) &&
            this.validateEmail(this.state.user.email2) &&
            this.validateNumber(this.state.user.age) &&
            this.validateNumber(this.state.user.phone)
        });
      }
    );
  };

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

    const { name, age, email1, email2, city, phone } = this.state.user;
    this.setState({
      submitted: true
    });

    if (
      name !== "" &&
      age !== "" &&
      email1 !== "" &&
      email2 !== "" &&
      city !== "" &&
      phone !== ""
    ) {
      console.log("User created : ", this.state.user);
    } else {
      console.log("Error creating user");
    }
  };

  isTouched = inputName => {
    const inputs = [...this.state.isTouched];

    if (!inputs.includes(inputName)) {
      inputs.push(inputName);

      this.setState({
        isTouched: inputs
      });
    }
  };

  render() {
    const { submitted, invalidEmail, user } = this.state;
    return (
      <div className="App">
        <form onSubmit={this.handleSubmit}>
          <div>
            <label htmlFor="name">Name</label>
            <input
              type="text"
              id="name"
              onFocus={() => this.isTouched("name")}
              name="name"
              value={user.name}
              onChange={this.handleChange}
            />
            {!user.name && this.state.isTouched.includes("name") && (
              <div style={{ color: "red" }}>Name is required</div>
            )}
          </div>
          <div>
            <label htmlFor="age">Age</label>
            <input
              type="text"
              id="age"
              name="age"
              onFocus={() => this.isTouched("age")}
              value={user.age}
              onChange={this.handleChange}
            />
            {submitted && !user.age && (
              <div style={{ color: "red" }}>Age is required</div>
            )}
            {!this.validateNumber(user.age) &&
              this.state.isTouched.includes("age") && (
                <div style={{ color: "red" }}>Age must be numeric</div>
              )}
          </div>
          <div>
            <label htmlFor="email1">Email 1</label>
            <input
              type="email"
              id="email1"
              name="email1"
              onFocus={() => this.isTouched("email1")}
              value={user.email1}
              onChange={this.handleChange}
            />
            {submitted && !user.email1 && (
              <div style={{ color: "red" }}>Email 1 is required</div>
            )}
            {!this.validateEmail(this.state.user.email1) &&
              this.state.isTouched.includes("email1") && (
                <div style={{ color: "red" }}>Email is invalid</div>
              )}
          </div>
          <div>
            <label htmlFor="email2">Email 2</label>
            <input
              type="email"
              id="email2"
              name="email2"
              onFocus={() => this.isTouched("email2")}
              value={user.email2}
              onChange={this.handleChange}
            />
            {submitted && !user.email2 && (
              <div style={{ color: "red" }}>Email 2 is required</div>
            )}
            {!this.validateEmail(this.state.user.email2) &&
              this.state.isTouched.includes("email2") && (
                <div style={{ color: "red" }}>Email is invalid</div>
              )}
          </div>
          <div>
            <label htmlFor="phone">Phone</label>
            <input
              type="text"
              id="phone"
              name="phone"
              value={user.phone}
              onFocus={() => this.isTouched("phone")}
              onChange={this.handleChange}
            />
            {submitted && !user.phone && (
              <div style={{ color: "red" }}>Phone is required</div>
            )}
            {!this.validateNumber(user.phone) &&
              this.state.isTouched.includes("phone") && (
                <div style={{ color: "red" }}>Phone must be numeric</div>
              )}
          </div>
          <div>
            <label htmlFor="city">City</label>
            <select
              id="city"
              name="city"
              value={user.city}
              onChange={this.handleChange}
            >
              <option value="" disabled>
                Select
              </option>
              <option value="Delhi">Delhi</option>
              <option value="Mumbai">Mumbai</option>
              <option value="Pune">Pune</option>
            </select>
            {submitted && !user.city && (
              <div style={{ color: "red" }}>City is required</div>
            )}
          </div>
          <button disabled={!this.state.isValidForm} type="submit">
            Submit
          </button>
        </form>
      </div>
    );
  }
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
);
</script>
0 голосов
/ 29 февраля 2020

В моей голове, кажется, имеет смысл иметь два отдельных состояния. Если бы я просто не хотел создавать другое состояние, я бы сказал, что удобочитаемость и простота должны быть приоритетом.

...