在表单提交反应挂钩之前跳过验证

Skipping validation before form submission react-hooks

我的表单提交会在提交错误输入时跳过显示验证错误消息。出现错误消息时如何阻止提交?

我的代码:

import React, { useState } from "react";

const App = () => {
  const [formData, setFormData] = useState({ name: "" });
  const [formError, setFormError] = useState({});
  const [isSubmit, setIsSubmit] = useState(false);
  const [formSubmitted, setFormSubmitted] = useState(false);

  const validate = () => {
    const errors = {};
    console.log("2. errors: ", errors); //<=== point 2.
    if (formData.name.length === 0) {
      errors.name = "name required";
    }
    console.log("3. errors: ", errors);  //<=== point 3.
    return errors;
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    setIsSubmit(true);
    console.log("1. formData: ", formData);  //<=== point 1.
    setFormError(validate(formData));
    console.log("4. formError: ", formError);  //<=== point 4.

    // This is true only if formError is empty object
    if (
      Object.keys(formError).length === 0 &&
      formError.constructor === Object
    ) {
      console.log("5. sending data: ", formData.name);  //<=== point 5.
      // Sending data to API here
      setIsSubmit(false);
      setFormSubmitted(true);
      return;
    }

    setIsSubmit(false);
    return;
  };

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData({ ...formData, [name]: value });
  };

  return (
    <>
      {formSubmitted ? (
        <p>Thank you</p> //<=== Thank you prhase
      ) : (
        <form onSubmit={handleSubmit}>
          <label htmlFor="name">Your name:</label>
          <input
            type="text"
            name="name"
            value={formData.name}
            onChange={handleChange}
          />
          {formError.name && <p>{formError.name}</p>}
          {isSubmit ? (
            <p>Sending...</p>
          ) : (
            <input type="submit" value="Submit" />
          )}
        </form>
      )}
    </>
  );
};

export default App;

提交空输入(错误输入)时的控制台:

1. formData:  {name: ''}
2. errors:  {}
3. errors:  {name: 'name required'}
4. formError:  {}
5. sending data:  

使用输入“test”(右输入)提交时的控制台:

1. formData:  {name: 'test'}
2. errors:  {}
3. errors:  {}
4. formError:  {}
5. sending data:  test

当我提交正确的输入时,表单会按照我的意愿运行。

submit right input -> input validation -> no error found -> send data -> show "Thank you" phrase

但是如果我输入错误。

submit wrong input -> input validation -> error found -> append error message -> but still return empty object (to formError) -> send empty input -> show "Thank you" phrase

问题在第 4 点,validate() 函数不会 return 错误消息。在我使用 API 的实际文件中,在提交错误输入时它会显示错误消息(例如 formError.name)(需要 1 到 2 秒才能将数据发送到 CMS)但提交仍然会通过并显示“谢谢”的短语。我怎样才能解决这个问题?谢谢。

状态更新不会同步发生。

您可以提取变量中的错误(在下面的示例中命名为 errors)并根据该变量而不是状态执行条件逻辑。

import React, { useState } from "react";

const App = () => {
  const [formData, setFormData] = useState({ name: "" });
  const [formError, setFormError] = useState({});
  const [isSubmit, setIsSubmit] = useState(false);
  const [formSubmitted, setFormSubmitted] = useState(false);

  const validate = () => {
    const errors = {};
    if (formData.name.length === 0) {
      errors.name = "name required";
    }
    return errors;
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    setIsSubmit(true);
    const errors = validate(formData); // extracting here
    setFormError(errors); // setting state using the extracted value

    // validating using the extracted value
    if (Object.keys(errors).length === 0 && errors.constructor === Object) {
      // Sending data to API here
      setIsSubmit(false);
      setFormSubmitted(true);
      return;
    }

    setIsSubmit(false);
    return;
  };

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData({ ...formData, [name]: value });
  };

  return (
    <>
      {formSubmitted ? (
        <p>Thank you</p> //<=== Thank you prhase
      ) : (
        <form onSubmit={handleSubmit}>
          <label htmlFor="name">Your name:</label>
          <input
            type="text"
            name="name"
            value={formData.name}
            onChange={handleChange}
          />
          {formError.name && <p>{formError.name}</p>}
          {isSubmit ? (
            <p>Sending...</p>
          ) : (
            <input type="submit" value="Submit" />
          )}
        </form>
      )}
    </>
  );
};

export default App;