Carl Rippon

Building SPAs

Carl Rippon
BlogBooks / CoursesAbout
This site uses cookies. Click here to find out more

Successful Submission in React Hook Form

September 01, 2020
reacttypescript

A critical part of a form entry process is the submission of the form. This part of the process is always interesting when using a 3rd party library such as React Hook Form. One common fundamental task is letting the user know that the submission was successful. So, how do this in React Hook Form? Let’s find out.

React Hook Form Successful Submission

An example

We have a simple form that has been implemented using React Hook Form. The form captures a users name:

type FormData = {
  name: string;
};

export default function App() {
  const { register, handleSubmit, errors } = useForm<FormData>();

  const submitForm = async (data: FormData) => {
    console.log("Submission starting", data);
    const result = await postData(data);
    console.log("Submitting complete", result.success);
  };
  return (
    <div className="app">
      <form onSubmit={handleSubmit(submitForm)}>
        <div>
          <input
            ref={register({ required: true })}
            type="text"
            name="name"
            placeholder="Enter your name"
          />
        </div>
        {errors.name && errors.name.type === "required" && (
          <div className="error">You must enter your name</div>
        )}
      </form>
    </div>
  );
}

The name field on the form is mandatory. We output a validation error if this hasn’t been populated, using the errors object from React Hook Form.

The form submission logic calls a postData function which sends the form to the server. Our mock implementation of postData is below:

const postData = ({ name }: FormData): Promise<postDataResult<FormData>> => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(`${name} saved.`);
      resolve({ success: true });
    }, 100);
  });
};

This simulates a call to the server and returns that the submission was successful.

submitForm is only invoked when validation passes

The forms validation checks fail if the user presses Enter in the name input before entering anything. In this case, our submitForm function will not be invoked by React Hook Form. This means that the logic in submitForm doesn’t need to check whether the form is valid - we can assume it is valid.

Nice!

Detecting when the form is being submitted

Typically we want to disable a form while the submission process is happening. React Hook Form has a handy formState variable that contains whether the form is being submitted:

const {
  register,
  handleSubmit,
  errors,
  formState,} = useForm<FormData>();

We can use this to disable the input element while submission is happening:

<input
  ref={register({
    required: { value: true, message: "You must enter your name" }
  })}
  type="text"
  name="name"
  placeholder="Enter your name"
  disabled={formState.isSubmitting}/>

We use the isSubmitting variable within formState to determine whether the form is being submitted and bind this to the input’s disabled property.

It is important to note that when formState changes, the form is rerendered.

When the submission is finished, isSubmitting will be set to false which means the input element becomes enabled again.

Detecting when the form has been submitted

We want to render a message to the user when the form has been successfully submitted. The formState variable also contains a isSubmitted variable. Let’s give this a try:

<form onSubmit={handleSubmit(submitForm)}>
  ...
  {formState.isSubmitted && (
    <div className="success">Form submitted successfully</div>
  )}
</form>

So, we output a success message when isSubmitted is true.

If the user presses Enter before filling in their name, we get the success message and the validation error:

Submitted issue

Not quite what we require!

So, isSubmitted only indicates whether the form has been submitted - not whether it was successfully submitted. This makes sense really because React Hook Form only controls part of the submission. For example, problems could happen on the server part of the submission that it doesn’t know about.

Detecting when the form has been successfully submitted

We need to create our own state for whether the form has been successfully submitted:

const [
  isSuccessfullySubmitted,
  setIsSuccessfullySubmitted,
] = React.useState(false);

The state is initialized to false when the form is first loaded.

We set this state after the form has been posted to the server:

const submitForm = async (data: FormData) => {
  console.log("Submission starting", data);
  const result = await postData(data);
  console.log("Submitting complete", result.success);
  setIsSuccessfullySubmitted(result.success);};

We can then use isSuccessfullySubmitted to render the success message:

{isSuccessfullySubmitted && (
  <div className="success">Form submitted successfully</div>
)}

Now the success message doesn’t appear until the user has successfully submitted the form:

Successful submission

Cool!

We can also add isSuccessfullySubmitted to the disabled property binding on the input element, so that it is disabled when the form has been successfully submitted:

<input
  ...
  disabled={formState.isSubmitting || isSuccessfullySubmitted}/>

You can see this working example in full in the CodeSandbox at https://codesandbox.io/s/react-hook-form-submission-state-c10md?file=/src/App.tsx

Wrap up

isSubmitted in React Hook Form’s formState indicates whether the form has been submitted and not necessarily whether it was successfully submitted. We use our own state to indicate successful submission, which we can set in our submission function.

Did you find this post useful?

Let me know by sharing it on Twitter.
Click here to share this post on Twitter

If you to learn more about using TypeScript with React, you may find my course useful:

Using TypeScript with React

Using TypeScript with React
Find out more

Want more content like this?

Subscribe to receive notifications on new blog posts and courses

Required
© Carl Rippon
Privacy Policy