Do not reset form fields on action submit
Unanswered
Xiasi Dog posted this in #help-forum
Xiasi DogOP
Hello, I was just wondering. I have a login form that contains username and password fields. When the user submits the form, it runs a simple server action that checks the validity of the credentials. If they aren't valid it returns an object with an error field which I then read using the
My question is, is there a way to prevent the submit action from resetting the form? I don't want the need for the user to retype all their credentials when they enter something incorrectly.
useActionState hook. My question is, is there a way to prevent the submit action from resetting the form? I don't want the need for the user to retype all their credentials when they enter something incorrectly.
24 Replies
Sandwich Tern
I don't know your code but can't you prevent it by using onSubmit on the form ?
And the smth like event.preventDefault()
@Xiasi Dog Hello, I was just wondering. I have a login form that contains username and password fields. When the user submits the form, it runs a simple server action that checks the validity of the credentials. If they aren't valid it returns an object with an error field which I then read using the `useActionState` hook.
My question is, is there a way to prevent the submit action from resetting the form? I don't want the need for the user to retype all their credentials when they enter something incorrectly.
pretty sure you have to explicitly reset the form, form actions don't reset the state automatically. see here: https://debug-git-nextjs-form-joulev-proj.vercel.app
@joulev pretty sure you have to explicitly reset the form, form actions don't reset the state automatically. see here: <https://debug-git-nextjs-form-joulev-proj.vercel.app>
Xiasi DogOP
Weird, then I must be doing something wrong since my form keeps resetting.
Sandwich Tern
Can you share your code ?
It sounds like the page is reloading, so @Sandwich Tern's suggestion of
preventDefault is likely the fix here. But also, code to look at will help us 😁Asiatic Lion
I make the form data part of the state and have the action return it. Then set
defaultValue on all the the fields from that.Xiasi DogOP
Is the button supposed to have a
type="submit"?This is how the form component looks like:
"use client";
const SignInForm = () => {
const [state, formAction] = useActionState(handleUsernamePasswordLogin, { error: "" });
const { pending } = useFormStatus();
const [showPassword, setShowPassword] = useState(false);
return (
<form className="mt-8 flex flex-col pb-4 md:pb-8" action={formAction}>
{/* Username/Email Input Field */}
<Input
label="Username or Email"
placeholder="Enter your username or email"
name="username"
autoComplete="username"
required
iconLeft={<User2Icon className="icon text-secondary" />}
/>
{/* Password Input Field */}
<Input
label="Password"
placeholder="Fill me!"
name="password"
type={showPassword ? "text" : "password"}
autoComplete="current-password"
error={state.error}
required
inputClass={!showPassword && "tracking-widest placeholder:tracking-normal"}
iconLeft={<KeyRoundIcon className="icon text-secondary" />}
iconRight={
<button
type="button"
className="-mr-2 select-none p-2"
onClick={() => setShowPassword(!showPassword)}>
{showPassword ? (
<EyeIcon className="icon text-secondary" />
) : (
<EyeOffIcon className="icon text-tertiary" />
)}
</button>
}
/>
{/* Reset Password Trigger */}
<Link href={""} className="-mt-5 self-end text-sm font-medium text-brand">
Forgot password?
</Link>
{/* Sign In Button */}
<button
className="btn primary small brand mt-4 disabled:opacity-40"
type="submit"
disabled={pending}>
Sign in
<MoveRightIcon className="btn-arrow" />
</button>
</form>
);
};I'm also using the
canary branch of react, react-dom and nextYeah - looks like a
Instead. So you call a local method, cancel any other form actions, and then pass off to
preventDefault issue. I would: const handleSubmit = (event) => {
event.preventDefault();
formAction(new FormData(event.target));
};
return (
<form className="mt-8 flex flex-col pb-4 md:pb-8" onSubmit={handleSubmit}>Instead. So you call a local method, cancel any other form actions, and then pass off to
formAction@Ben Dechrai It sounds like the page is reloading, so <@326050424492916736>'s suggestion of `preventDefault` is likely the fix here. But also, code to look at will help us 😁
form actions are automatically preventDefault'd.
Yeah, if it's not the preventDefault either (thanks for the info @joulev!) then it's looking like it should work here too.
Sandwich Tern
Maybe you can try smth simple to see if this is the action handleUsernamePasswordLogin that make this issue. Just try to implement smth like
const handleSubmit = () => {
console.log("submit")
};
return (
<form className="mt-8 flex flex-col pb-4 md:pb-8" onSubmit={handleSubmit}>
and then tell us if it still reset the form
const handleSubmit = () => {
console.log("submit")
};
return (
<form className="mt-8 flex flex-col pb-4 md:pb-8" onSubmit={handleSubmit}>
and then tell us if it still reset the form
@Ben Dechrai Yeah - looks like a `preventDefault` issue. I would:
const handleSubmit = (event) => {
event.preventDefault();
formAction(new FormData(event.target));
};
return (
<form className="mt-8 flex flex-col pb-4 md:pb-8" onSubmit={handleSubmit}>
Instead. So you call a local method, cancel any other form actions, and then pass off to `formAction`
Xiasi DogOP
This seems to work, but now it's complaining that this is not the recommended use of actions.
@joulev honestly the code looks fine for me. could you reproduce this bug in a minimal reproduction repository so i can clone and test it locally?
Xiasi DogOP
Here you go. This should be a minimal reproduction. https://github.com/vdemcak/nextjs-form-minimal
I'm stumped 🤷♂️ The docs say
useActionState should handle the preventDefault, but checking your code out, I see the same error, and adding a handler, I see the error go away. Where do you see the complaint that this is not the recommended use of actions?I've just implemented the example from https://react.dev/reference/react/useActionState and added a text input field. I'm also seeing that one reset after the action runs. It looks like preventDefault is indeed initiated by
useActionState, but that form fields are reset afterwards. I can't see anything in the documentation about the default state of the form after submission, or how to override it. I suspect for your use case, it would be better to stick with onSubmit and call formAction from that handler.@Xiasi Dog Here you go. This should be a minimal reproduction. https://github.com/vdemcak/nextjs-form-minimal
appears to be a react bug. if you downgrade to next 14 and react 18.3.1 (and use
useFormState instead of useActionState, since useActionState doesn't work in 18.3.1), the issue goes awayi'll dig deeper to see whether this is a bug or an intentional decision – i certainly don't want my forms to automatically reset, either
yes, [it is an intentional feature](https://github.com/facebook/react/pull/28804) and there are more discussions against this feature in [this issue](https://github.com/facebook/react/issues/29034).
tl;dr: either use controlled inputs, or use
i don't agree with this decision at all but it is what it is, unfortunately.
tl;dr: either use controlled inputs, or use
onSubmit+function handleSubmit(event) {
+ event.preventDefault();
+ const formData = new FormData(event.target);
+ startTransition(() => action(formData));
+}
...
-<form action={action}>
+<form onSubmit={handleSubmit}>i don't agree with this decision at all but it is what it is, unfortunately.
thats so weird as so much of the coolness of server actions were that they dont reset fields (ie revalidatePath)
@joulev yes, [it is an intentional feature](<https://github.com/facebook/react/pull/28804>) and there are more discussions against this feature in [this issue](<https://github.com/facebook/react/issues/29034>).
tl;dr: either use controlled inputs, or use `onSubmit`
diff
+function handleSubmit(event) {
+ event.preventDefault();
+ const formData = new FormData(event.target);
+ startTransition(() => action(formData));
+}
...
-<form action={action}>
+<form onSubmit={handleSubmit}>
i don't agree with this decision at all but it is what it is, unfortunately.
also you should still keep
action={action} for progressive enhancement right (as the preventDefault will stop it being used)?