Loading State Not working In Form Component
Unanswered
Arinji posted this in #help-forum
ArinjiOP
form.tsx
Action:
The Loader does not Show Up, any idea why? The variables do get logged out correctly
"use client";
import { useToast } from "@/hooks/useToast";
import { CreateTodoAction } from "@/lib/actions/todo/create";
import { Loader2 } from "lucide-react";
import {
experimental_useFormState as useFormState,
experimental_useFormStatus as useFormStatus,
} from "react-dom";
export function Form() {
const initialState = {
type: "success",
message: "",
id: 0,
};
const [state, formAction] = useFormState(CreateTodoAction, initialState);
const { pending } = useFormStatus();
useToast({
message: state.message,
type: state.type,
successMessage: "Successfully Created Todo",
successRoute: `/dash/todo/${state.id}`,
});
return (
<form
action={formAction}
className=""
>
<div className="...">
<label htmlFor="name" className="">
Name
</label>
<input
type="text"
name="name"
id="name"
required
maxLength={50}
minLength={1}
className="..."
/>
</div>
<div className="...">
<label htmlFor="name" className="">
Description
</label>
<textarea
name="description"
id="description"
required
maxLength={100}
minLength={10}
className="..."
/>
</div>
<div className="...">
<button
type="submit"
className="..."
>
{pending && <Loader2 className="animate-spin" />} <p>Create Todo</p>
</button>
</div>
</form>
);
}Action:
"use server";
export async function CreateTodoAction(prevState: any, formData: FormData) {
const name = formData.get("name");
const desc = formData.get("description");
setTimeout(() => {
console.log(name, desc);
}, 2000);
return {
message: "Todo Created",
success: true,
};
}The Loader does not Show Up, any idea why? The variables do get logged out correctly
13 Replies
ArinjiOP
Thing is, this works
Where i call this in the form, you can see the loader, but why is this happening :/
"use client";
import { useToast } from "@/hooks/useToast";
import { CreateTodoAction } from "@/lib/actions/todo/create";
import { Loader2 } from "lucide-react";
import { experimental_useFormState as useFormState } from "react-dom";
import { SubmitButton } from "./submit";
export function Form() {
const initialState = {
type: "success",
message: "",
id: 0,
};
const [state, formAction] = useFormState(CreateTodoAction, initialState);
useToast({
message: state.message,
type: state.type,
successMessage: "Successfully Created Todo",
successRoute: `/dash/todo/${state.id}`,
});
return (
<form
action={formAction}
className="w-full xl:w-[70%] scale-90 md:scale-100 h-full flex flex-col items-center justify-center gap-4 bg-slate-300 rounded-md border-4 shadow-[4px_4px_0_#000] p-4 border-black"
>
<div className="w-full h-full flex flex-col items-start justify-center gap-2">
<label htmlFor="name" className="text-2xl text-black font-bold">
Name
</label>
<input
type="text"
name="name"
id="name"
required
maxLength={50}
minLength={1}
className="w-full max-w-[700px] px-2 h-10 ml-5 rounded-md outline-1 bg-gray-200 outline-gray-200 font-medium "
/>
</div>
<div className="w-full h-full flex flex-col items-start justify-center gap-2">
<label htmlFor="name" className="text-2xl text-black font-bold">
Description
</label>
<textarea
name="description"
id="description"
required
maxLength={100}
minLength={10}
className="w-full max-w-[700px] px-2 py-2 h-20 ml-5 rounded-md outline-1 bg-gray-200 outline-gray-200 font-medium "
/>
</div>
<SubmitButton />
</form>
);
}Where i call this in the form, you can see the loader, but why is this happening :/
ArinjiOP
Ive been going through the docs, i dont see what im doing wrong
ArinjiOP
Bump 

first thing i see in the action
the timeout will not work. It will return immediately.
You have to await a promise with a timeout to make it work like that:
"use server";
export async function CreateTodoAction(prevState: any, formData: FormData) {
const name = formData.get("name");
const desc = formData.get("description");
setTimeout(() => {
console.log(name, desc);
}, 2000);
return {
message: "Todo Created",
success: true,
};
}the timeout will not work. It will return immediately.
You have to await a promise with a timeout to make it work like that:
await new Promise((resolve) => setTimeout(resolve, 2000))@KINXZ first thing i see in the action ts
"use server";
export async function CreateTodoAction(prevState: any, formData: FormData) {
const name = formData.get("name");
const desc = formData.get("description");
setTimeout(() => {
console.log(name, desc);
}, 2000);
return {
message: "Todo Created",
success: true,
};
}
the timeout will not work. It will return immediately.
You have to await a promise with a timeout to make it work like that:
ts
await new Promise((resolve) => setTimeout(resolve, 2000))
ArinjiOP
Yea i added some real query so it takes time now, but it's still now showing the loader
just an experiment but would it work if you wrap
useToast({
message: state.message,
type: state.type,
successMessage: "Successfully Created Todo",
successRoute: `/dash/todo/${state.id}`,
}); in a useEffect?useEffect(() => {
useToast({
message: state.message,
type: state.type,
successMessage: "Successfully Created Todo",
successRoute: `/dash/todo/${state.id}`,
})
}, [useToast, state]
)😄 yeah
ArinjiOP
but i dont see how the useFormStatus would matter cause of that :(
could it be that its experimental so its broken?
no idea tbh. In a project of mine i did use toasts too on a form. I used useTransition with onSubmit on the form
this worked pretty well