Replies: 18 comments 31 replies
-
Code example? Forms have a reset method, or you could alternatively have a button with type "reset", but without a code example, it is a bit hard to guide you in the right direction. |
Beta Was this translation helpful? Give feedback.
-
Trying to figure out the same thing and not finding anything in the docs. There's no reset method on FormData at the moment. Using the latest version of next (currently 14.0.3).
|
Beta Was this translation helpful? Give feedback.
-
Any new things anybody found here? I want to be able to reset the form in my server component. |
Beta Was this translation helpful? Give feedback.
-
Nevermind. As mentioned in the video of Lee Robinson (at around minute 18) https://www.youtube.com/watch?v=8DyzsSWNcDE&ab_channel=LeeRobinson we lose nothing if we use a client component instead of a server component so it makes sense to make the form a client component. |
Beta Was this translation helpful? Give feedback.
-
https://react.dev/reference/react-dom/components/form#optimistically-updating-form-data ![]() And if you use
|
Beta Was this translation helpful? Give feedback.
-
I created an issue on the react side since this seems to be an open point. |
Beta Was this translation helpful? Give feedback.
-
i get the solution
you can check the full code in my github link ![]() |
Beta Was this translation helpful? Give feedback.
-
Another way to reset the form is by using the prop key. I'm not entirely sure how recommended this approach is, but you can return a new state from the action and then use a key to reset the form. Here's a basic example: "use client";
import { useFormState } from "react-dom";
import { addPost } from "./actions";
export default function Home() {
const [state, action] = useFormState(addPost, { error: null });
return (
<main>
<form action={action} key={state?.resetKey}>
<input type="text" placeholder="Title" name="title" />
<button>Submit</button>
</form>
</main>
);
} "use server";
import { redirect } from "next/navigation";
export const addPost = (prevState, formData: FormData) => {
const title = formData.get("title")?.toString();
if (!title) {
return {
resetKey: prevState.resetKey,
error: "Title is required",
};
}
const post = createPost(title);
return {
error: null,
data: post,
resetKey: post.id,
};
};
function createPost(title: string) {
return {
id: Date.now(),
title,
};
} |
Beta Was this translation helpful? Give feedback.
-
Any new solution to this? I have a "use server" form and I can't clear my form. Seems like it should be something trivial right? |
Beta Was this translation helpful? Give feedback.
-
'use client'
import { useRef } from "react";
import { addTodo } from "../actions/addTodo";
function TodoForm() {
const ref = useRef<HTMLFormElement>(null);
return (
<form
ref={ref}
action={async (formData) => {
await addTodo(formData);
ref.current?.reset();
}}
>
<input
type="text"
placeholder="Enter your task here"
name="todo"
/>
<input name="isDone" type="checkbox" hidden />
<button>
<svg
width="24"
height="24"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
type="submit"
>
<path stroke="none" d="M0 0h24v24H0z" />
<circle cx="12" cy="12" r="9" />
<line x1="9" y1="12" x2="15" y2="12" />
<line x1="12" y1="9" x2="12" y2="15" />
</svg>
<span>Add</span>
</button>
</form>
);
}
export default TodoForm; and action "use server";
import { revalidatePath } from "next/cache";
export async function addTodo(formData: FormData) {
const rawFormData = {
content: formData.get("todo"),
date: new Date().toISOString(),
isDone: formData.get("isDone") === "on" ? "true" : "false",
};
await fetch("http://localhost:8000/todos/add", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(rawFormData),
});
formData.set("todo", " ");
revalidatePath("/");
} |
Beta Was this translation helpful? Give feedback.
-
I was running into this issue and using |
Beta Was this translation helpful? Give feedback.
-
This is my solution 'use client'
import { Input } from '@/components/ui/input'
import { Button } from '@/components/ui/button'
import { createMessage } from '@/lib/actions'
import { useState } from 'react'
export function NewMessageForm({
serverId,
channelId
}: {
serverId: string
channelId: string
}) {
const [content, setContent] = useState('')
return (
// add `onSubmit={() => setContent('')` to form element
<form action={createMessage} onSubmit={() => setContent('')}>
<div className="flex gap-2 p-2">
<input type="text" name="serverId" value={serverId} hidden readOnly />
<input type="text" name="channelId" value={channelId} hidden readOnly />
<Input
name="content"
value={content}
onChange={(e) => setContent(e.target.value)}
/>
<Button type="submit">Submit</Button>
</div>
</form>
)
} |
Beta Was this translation helpful? Give feedback.
-
In next.js 14.2 this is already fixed. |
Beta Was this translation helpful? Give feedback.
-
We have a custom Our component also handles the Form.tsximport { useEffect, useRef } from 'react';
export default function Form({
action,
children,
className,
state,
...rest
}: {
action: any;
children: React.ReactNode;
className?: string;
state: any;
rest?: React.HTMLProps<HTMLFormElement>;
}) {
const formRef = useRef<HTMLFormElement>(null);
useEffect(() => {
if (state.success) {
formRef?.current?.reset();
}
}, [state.success]);
return (
<form action={action} className={className} ref={formRef} {...rest}>
{children}
<p aria-live="polite" className="sr-only" role="status">
{state?.message}
</p>
</form>
);
} Example usage'use client';
import Form from '@/components/Form';
import { createBetaUser } from '@/app/auth/actions';
import { Field, Label } from '@/components/catalyst/fieldset';
import { initialFormState } from '@/lib/constants';
import { Input } from '@/components/catalyst/input';
import { useEffect } from 'react';
import { useFormState } from 'react-dom';
export default function BetaSignup() {
const [state, action] = useFormState(createBetaUser, initialFormState);
useEffect(() => {
if (state.success) {
// Do something that will only fire once on every unique success response.
}
}, [state.success]);
return (
<Form state={state} action={action}>
<Field>
<Label>Email</Label>
<Input
name="email"
placeholder="[email protected]"
required
type="email"
/>
</Field>
</Form>
);
} Server actionexport async function createBetaUser(
_prevState: {
status: string;
message?: string;
},
formData: FormData
) {
// ... do stuff.
return {
success: new Date().getTime(), // Providing a unique identifier here is important to allow the React component to respond to a changing `success` value.
message: 'good',
};
} |
Beta Was this translation helpful? Give feedback.
-
Try this method const Page = () => {
const [resetKey, setResetKey] = useState(0);
const submit = async (formData) => {
await handleSubmit(formData);
setResetKey((prev) => prev + 1);
};
return (
<div>
<form key={resetKey} action={submit}>
<input name="myinput" type="text" />
</form>
</div>
);
}; |
Beta Was this translation helpful? Give feedback.
-
This question has been around for a while, but I noticed there are multiple approaches to handling this situation. I wanted to share my method of resetting form inputs after a server action mutation. As highlighted in the Next.js documentation, I leverage Here’s an example of how to achieve this using TypeScript: Example of a client componentimport { useFormState } from "react-dom";
import { useEffect, useRef, useState } from "react";
import ExampleSubmitButton from "@/components/example-submit-button";
import exampleAction, {
IMyInitialState, // Interface to define the initial state
} from "../_actions/example-action";
const initialState: IMyInitialState = {
errors: undefined,
success: undefined,
};
const MyClientComponent = () => {
// Passing the initial state and action to useFormState
const [state, formAction] = useFormState(exampleAction, initialState);
// Additional state controlled by the result of the server action
const [showSuccessDialog, setShowSuccessDialog] = useState(false);
const [buttonState, setButtonState] = useState<"idle" | "success" | "error">("idle");
// Ref to the form, used to clear the form fields upon success
const formRef = useRef<HTMLFormElement>(null);
const clearForm = () => {
if (formRef.current) {
formRef.current.reset();
}
};
// Effect hook to handle action state changes
useEffect(() => {
if (state?.errors) {
setButtonState("error");
return;
}
if (state?.success) {
setShowSuccessDialog(true);
setButtonState("success");
clearForm();
}
}, [state?.errors, state?.success]);
return (
<div>
<form ref={formRef} action={formAction} className="space-y-4 mb-8">
{/* ----- Form fields go here ------ */}
<ExampleSubmitButton
type="submit"
idle="Idle state title"
setState={setButtonState}
state={buttonState}
success="Success state title"
error="Error state title"
/>
</form>
<SuccessDialog
isDialogOpen={showSuccessDialog}
setIsDialogOpen={setShowSuccessDialog}
/>
</div>
);
} Example of the server action used by the client component'use server';
export interface IMyInitialState {
// Structure your initial state as needed
errors?: {
global?: string[] // Global errors (e.g., 500 status)
email?: string[] // Field-specific errors
name?: string[]
message?: string[]
},
success?: boolean // Action status
}
const exampleAction = async (_: IMyInitialState, formData: FormData): Promise<IMyInitialState> => {
try {
// Your action logic here...
await new Promise((resolve) => setTimeout(resolve, 1000));
return {
errors: undefined,
success: true,
};
} catch {
return {
errors: {
global: ['An error occurred.'],
},
success: false,
};
}
}
export default exampleAction; Key Points:
|
Beta Was this translation helpful? Give feedback.
-
Here is a solution for the Next.js Form component: https://nextjs.org/docs/app/api-reference/components/form 'use client';
import React, { type ReactNode } from 'react';
import Form from 'next/form';
/**
* Search form properties.
*/
interface SearchFormProps {
/**
* Search URL.
*/
searchUrl: string
children: ReactNode
}
/**
* Search form.
*
* @param param0
*/
export default function SearchForm({
searchUrl,
children
}: SearchFormProps) {
/**
* Reset the form state e.g. clear all input fields.
*
* @param event
*/
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
//reset form
const form = event.currentTarget;
//Note: using timer because Next.js needs the values first
setTimeout(() => {
form.reset();
//debug
//console.log('Search form reset.');
}, 100);
};
return (
<Form action={searchUrl} onSubmit={handleSubmit}>
{children}
</Form>
);
} |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Summary
Hey,
How to clear / reset input after server mutation ?
I don't see any tutorial or so.
Please help.
Many Thanks!
Additional information
No response
Example
No response
Beta Was this translation helpful? Give feedback.
All reactions