Next.js Discord

Discord Forum

How to reset forms?

Answered
Spectacled bear posted this in #help-forum
Open in Discord
Spectacled bearOP
How to reset forms in Next.js?
As long as you don't have an action attribute on the <form> element, it uses the default browser behavior (submit and reset).
But once the action attribute is set it doesn't reset anymore after submission - why?

export default function Form() {
    const [state, formAction] = useFormState(serverAction, initialState)

    return <>
        <form action={formAction}>
            <label htmlFor="name">Your Name</label>
            <input type="text" name="name" id="name" defaultValue='' required />
            <button type="submit">Send</button>
        </form>
    </>
}
Answered by Ray
  await action(data)
  ref.current?.reset()

it just call reset after the action finish
View full answer

31 Replies

is the useFormState imported from "react"?
or any custom hook?
@dr_kakapo is the `useFormState` imported from "react"?
Spectacled bearOP
yes, useFormState
@aardani Because now form is a client conponent and is being handled using client-side js by react. If you want it to reset, you can try not using useFormState
Spectacled bearOP
then how would you implement a reset?
having forms as client components and handling their data via server actions along with useFormState() seems to be the recommended way in nextjs14 with app router.
I can't imaging that they didn't think about resetting those forms after submission.
@Spectacled bear then how would you implement a reset? having forms as client components and handling their data via server actions along with `useFormState()` seems to be the recommended way in nextjs14 with app router. I can't imaging that they didn't think about resetting those forms after submission.
"use client";

import { action } from "@/lib/action";
import { useState, useRef } from "react";

export function Form() {
  const formRef = useRef<HTMLFormElement>(null);
  const [errors, setErrors] = useState(null);
  return (
    <>
      {errors && <p>{errors}</p>}
      <form
        ref={formRef}
        action={async (formData) => {
          const { errors } = await action(formData);
          if (errors) {
            setErrors(errors);
            return;
          }
          formRef.current?.reset();
        }}
      >
        <input type="text" name="name" />
        <button>submit</button>
      </form>
    </>
  );
}
@Ray ts "use client"; import { action } from "@/lib/action"; import { useState, useRef } from "react"; export function Form() { const formRef = useRef<HTMLFormElement>(null); const [errors, setErrors] = useState(null); return ( <> {errors && <p>{errors}</p>} <form ref={formRef} action={async (formData) => { const { errors } = await action(formData); if (errors) { setErrors(errors); return; } formRef.current?.reset(); }} > <input type="text" name="name" /> <button>submit</button> </form> </> ); }
Spectacled bearOP
Thank you @Ray !
What do you think about this approach?:
import { useRef, useEffect } from 'react';
  
export function ResetForm() {
  const ref = useRef<HTMLFormElement | null>(null);
  const [formState, action] = useFormState(
    actions.serverActionToCall,
    { errors: {}, success: false }
  );
  
  useEffect(() => {
    if (formState.success) {
      ref.current?.reset();
    }
  }, [formState]);
  
  
  return <form ref={ref}>
    <input type="text" name="name" />
    <button type="submit">Submit</button>
  </form>
}
yea you could do that but I usually like to avoid useEffect as much as I can
@Ray yea you could do that but I usually like to avoid useEffect as much as I can
Spectacled bearOP
I also learned that using useEffect is considered rather bad practice🤔

My problem is that I don't really understand the whole useRef thing yet.
why?
Spectacled bearOP
probably just because i didn't use it before and it's not documented in next.js docs😇
I've just been wondering that you can pass ref as attribute in form elements.
Is this a nextjs feature, a react feature or an HTML feature?
its a react feature
Spectacled bearOP
Already found this docs.
Currently trying to wrap my head around this in order to understand what I can do with useRef and how it actually works.
react-hook-form also use it instead of useState
Spectacled bearOP
good to know.🤔
seems powerful.
but I'm still wondering why there's no "built-in" way to reset forms in next.js by default.
its still new, it will get better over time 😆
form action work without javascript, we can just redirect to different page instead of resetting the form
you can't reset the form without javascript, right?
Spectacled bearOP
true. good point.
but it's just super common to stay on the same page after sending a form, isn't it?
yes just use it with useRef
nothing wrong with useRef
Spectacled bearOP
Yes, I just need to practice more using it.
Why do you prefer useState over useEffect?
No, im not, they are different. But I would avoid useEffect
Spectacled bearOP
from what I understand when it comes to resetting forms in nextjs, we basically need something that re-renders the page in order to check if that useRef on the form changed.
and we can either use useState or useEffect to re-render the page.
because nextjs itself will not re-render the page automatically when we send the form which uses an action based on useFormState.
is that correct?
I think we can reset the form without re-render by using useRef only
  await action(data)
  ref.current?.reset()

it just call reset after the action finish
Answer
it's just like document.querySelector('form')?.reset()
Yep, Ray's approach is correct. I posted about this a few days ago. Have a look at the example https://sabin.dev/how-to-clear-your-forms-when-using-server-actions-in-nextjs
Spectacled bearOP
Thank you @Ray and @sabin !
This article summarized it perfectly and is a perfect fit for my solutions-reference sheet😁