Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Skipping validation before form submission react-hooks

My form Submission would skip showing validation error message when submitting wrong input. How can I prevent submission when error message is present?

my code:

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;

console when submitting empty input (wrong input):

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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

console when submitting with input "test" (right input):

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

When I submit a right input, the form would act as I wanted.

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

But if I submit wrong input.

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

The problem is at point 4, the validate() function wont return the error message. On my actual file with API, while submitting wrong input it will show the error message (e.g. formError.name) (takes 1 to 2 seconds to send data to CMS) but the submission will still goes thru and show "thank you" phrase. How can I fix this? Thank you.

>Solution :

State update doesn’t happen synchronously.

You can extract the error in a variable (named errors in the example below) and do the conditional logic based on that instead of the state.

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;
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading