I'm trying to use useFormStatus()
to change UI dynamically when the form is submitted and it's waiting to fetch the data.
I have a form component like
function onSubmit(data: z.infer<typeof FormSchema>) {
requestImg(data).then((imageStringify) => {
const binaryData = Buffer.from(imageStringify.image);
const imageBase64 = URL.createObjectURL(
new Blob([binaryData.buffer], { type: "image/jpeg" } /* (1) */)
);
setOpen(true);
setSource(imageBase64);
});
}
if (isDesktop) {
return (
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="w-2/3 space-y-6"
>
...
with requestImg(data)
being a server action.
I've then the Button component nested inside the <form>
in a different Button.tsx file
import { useFormStatus } from "react-dom";
import { Button } from "@/components/ui/button";
export default function ButtonSub() {
const { pending } = useFormStatus();
console.log(pending);
return (
<Button className="w-full" type="submit" aria-disabled={pending}>
{pending ? "Processing..." : "Submit"}
</Button>
);
}
The issue is that, when I click submit, the button text doesn't change to "Processing..."
It seems that works only if you're using the action keyword on the form. I've tried
<form
action={async (formData: FormData) => {
requestImg(formData).then((imageStringify) => {
const binaryData = Buffer.from(imageStringify.image);
const imageBase64 = URL.createObjectURL(
new Blob([binaryData.buffer], { type: "image/jpeg" } /* (1) */)
);
setSource(imageBase64);
setOpen(true);
});
}}
className="w-2/3 space-y-6"
>
but now the image generated with the byte8Array is broken. I have an image with a dynamic src filled with
const [source, setSource] = useState("");
<img src={source}/>
A solution I found without using the action keyword but still using server action calling it as a function was to use useTransition()
import { useState, useTransition } from "react";
const [isPending, startTransition] = useTransition();
function onSubmit(data: z.infer<typeof FormSchema>) {
startTransition(async () => {
... do your things ...
and the Submit Button client component
<Button
className="w-full"
type="submit"
disabled={isPending}
aria-disabled={isPending}
>
{isPending ? "Processing..." : "Submit"}
</Button>