处理多个布尔状态变量以进行验证

Dealing with multiple boolean state variables for validation

我正在 React 中构建一个表单,并具有验证用户提供的电子邮件和密码的功能:如果其中一个未通过验证,状态变量将从 true 翻转为 false,并出现错误有条件地呈现消息:

状态变量

const [isEmail, setEmail] = useState(true);
const [isPassword, setPassword] = useState(true);

验证函数

  const validateEmailAndPassword = (email, password) => {
    const emailRegEx =
      /^(([^<>()\[\]\.,;:\s@"]****************;
    email.match(emailRegEx) ? setEmail(true) : setEmail(false);
    password.length > 8 ? setPassword(true) : setPassword(false);
  };

错误信息

<p className="errors">{!isEmail ? errors.email : null}</p>

与其单独声明每个状态变量,不如将它们一起声明的最佳方式是什么,就像我在表单中对其他输入所做的那样?

完整文件如下:

import { useState, useEffect } from "react";

const Form = () => {
  const [{ email, password,colour }, setFormDetails] = useState({
    email: "",
    password: "",
    colour: ""
  });
  const [isEmail, setEmail] = useState(true);
  const [isPassword, setPassword] = useState(true);
  const [isTigerChecked, setTigerChecked] = useState(false);

  useEffect(() => {
    document.title = 'Contact form'
},[])


  const errors = {
    password: "Password needs to contain 8 or more characters",
    email: "Please enter a valid email",
  };

  const handleChange = (e) => {
    e.preventDefault();
    const { name, value } = e.target;
    setFormDetails((prevForm) => ({
      ...prevForm,
      [name]: value,
    }));
  };

  const validateEmailAndPassword = (email, password) => {
    const emailRegEx =
      /^(([^<>()\[\]\.,;:\s@"]+(\.[^<>()\[\]\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    email.match(emailRegEx) ? setEmail(true) : setEmail(false);
    password.length > 8 ? setPassword(true) : setPassword(false);
  };
  
  const handleClick = (e) => {
    e.target.checked ? setTigerChecked(true) : setTigerChecked(false)
  }

  const handleSubmit = (e) => {
    e.preventDefault();
    validateEmailAndPassword(email, password);
  };

  return (
    <div className="form-container">
      <p>Contact form</p>
      <form onSubmit={handleSubmit}>
        <input
          className="form-element"
          type="text"
          placeholder="Enter email address"
          name="email"
          onChange={handleChange}
        />
        <p className="errors">{!isEmail ? errors.email : null}</p>
        <input
          className="form-element"
          type="password"
          placeholder="Enter password"
          name="password"
          onChange={handleChange}
        />
        <p className="errors">{!isPassword ? errors.password : null}</p>
        <fieldset className="form-element">
          <legend>Please select a colour</legend>
          <select name="colour" id="colour" onChange = {handleChange}>
            <option value="Blue">Blue</option>
            <option value="Green">Green</option>
            <option value="Red">Red</option>
            <option value="Black">Black</option>
            <option value="Brown">Brown</option>
          </select>
        </fieldset>

        <fieldset className="form-element">
          <legend>Please select your animals</legend>
          <div className="checkbox">
            <input type="checkbox" id="bear" name="bear"  />
            <label for="bear"> Bear</label>
            <br></br>
            <input
              type="checkbox"
              id="Tiger"
              name="Tiger"
              onClick={handleClick}
            />
            <label for="Tiger"> Tiger</label>
            <br></br>
            <input type="checkbox" id="Snake" name="Snake" />
            <label for="Snake"> Snake</label>
            <br></br>
            <input type="checkbox" id="Donkey" name="Donkey" />
            <label for="Donkey"> Donkey</label>
            <br></br>
          </div>
        </fieldset>
        {isTigerChecked ? (
          <textarea
            id="tiger-type"
            name="tiger-type"
            rows="4"
            cols="50"
            placeholder="Please enter type of Tiger"
          />
        ) : null}
        <button type="submit">Submit</button>
      </form>
    </div>
  );
};

export default Form;

我会这样做: 摆脱 isEmail 和 isPassword 状态,并创建一个以空对象作为初始值的错误状态。

const [errors, setErrors] = useState({});

并将保存错误消息的错误对象的名称更改为 errorMessages

const errorMessages = {
    password: "Password needs to contain 8 or more characters",
    email: "Please enter a valid email",
}

在您的验证函数中,将一个 errorsObj 变量分配给一个空对象。如果电子邮件不匹配,请更新 errorsObj,以便将电子邮件密钥分配给错误对象中的电子邮件错误字符串(与密码相同)。

const errorsObj = {};
if(!email.match(emailRegEx)) errorsObj['email'] = errors['email']
if (!(password.length > 8)) errorsObj['password'] = errors['password']
setErrors(errorsObj);

现在有条件地呈现错误消息时,执行此操作

{!!errors['email'] && <p className="errors">{errors['email'}</p>}
{!!errors['password'] && <p className="errors">{errors['password'}</p>}

您还可以调整 handleChange 函数以正确更新错误

const handleChange = (e) => {
    e.preventDefault();
    const { name, value } = e.target;
    setFormDetails((prevForm) => ({
      ...prevForm,
      [name]: value,
    }));
    if (errors[name]) {
        setErrors(prevState => {
            delete prevState[name];
            return prevState;
        }
    }
  };