Loading...
Loading...
At the time of the writing this postuseFormStatus*hook in react is currently only available in React’s Canary and experimental channels. *
useFormStatus*is part of reacts effort for server component. useFormStatus is a react hook hence the prefix "use" that captures details on the most recent form submitted.
example: useFormStatusconst { pending, data, method, action } = useFormStatus();
useFormStatus retuns an obj with 4 valuespendingdatamethodaction
pending*tells you if the current form is doing an async task and if the form is actively submitting an action
example: using tailwind and reactimport { useFormStatus } from "react-dom";
import { type CSSProperties } from "react";
import LoadingSpinner from "@/components/loadingSpinner";
function SubmitButton({
copy = "submit",
className = "",
style = {},
}: {
style?: CSSProperties;
copy?: string;
className?: string;
}) {
const { pending } = useFormStatus();
const customClasses = Object.keys(style).length
? "hover:!bg-[#2d2d32] hover:!text-[#ffffff]"
: "hover:bg-[#f0db4e] hover:text-[#2d2d32]";
return (
<button
type="submit"
disabled={pending}
style={{ ...style }}
className={`rounded w-full font-mono bg-[#2d2d32] text-[#ffffff] p-2 mt-1 font-medium transition ${customClasses} ${className} `}
>
{pending ? (
<span className="w-full flex items-center justify-center">
<LoadingSpinner />
</span>
) : (
copy
)}
</button>
)
}
import { serverAction } from "@/app/actions";
import SubmitButton from '@component/submitButton'
function myForm(){
return (
<form action={serverAction}>
<div className="flex flex-col font-mono">
<div>
<label className="flex flex-col mb-3 font-mono">
<span className="mb-1 text-xs font-medium">First Name:</span>
<input
type="text"
name="firstName"
placeholder="Tony"
required
className="border p-2 focus:shadow-md focus:border-[#f0db4e] outline-0 rounded placeholder:text-small"
/>
</label>
<label className="flex flex-col mb-3 font-mono">
<span className="mb-1 text-xs font-medium">Last Name</span>
<input
type="text"
placeholder="Stark"
name="lastName"
required
className="border p-2 focus:shadow-md focus:border-[#f0db4e] outline-0 rounded placeholder:text-small"
/>
</label>
<label className="flex flex-col mb-3 font-mono">
<span className="mb-1 text-xs font-medium">Email</span>
<input
type="email"
placeholder="tonystark@starkindustries.com"
name="email"
required
className="border p-2 focus:shadow-md focus:border-[#f0db4e] outline-0 rounded placeholder:text-small"
/>
</label>
<legend className="mb-1 text-[#2d2d32] text-xs font-medium">
<span> Prior Experiance</span>
</legend>
<fieldset className="pr-2 py-2 flex flex-col md:flex-row align-center flex-wrap justify-between">
<div className="mb-3 md:mb-2 text-[#2d2d32] hover:font-bold transition-all font-medium text-sm">
<label
htmlFor={`${
props.idFor ? props.idFor + "beginner" : "beginner"
}`}
className="w-full cursor-pointer items-center flex"
>
<input
type="radio"
id={`${
props.idFor ? props.idFor + "beginner" : "beginner"
}`}
name="priorExperiance"
value="beginner"
required
/>
<span className="pl-2">Beginner</span>
</label>
</div>
<div className="mb-3 md:mb-0 md:mx-4 md:mb-2 lg:mx-6 text-[#2d2d32] hover:font-bold transition-all font-medium text-sm">
<label
htmlFor={`${
props.idFor
? props.idFor + "intermediate"
: "intermediate"
}`}
className="w-full cursor-pointer items-center flex"
>
<input
type="radio"
id={`${
props.idFor
? props.idFor + "intermediate"
: "intermediate"
}`}
name="priorExperiance"
value="intermediate"
className="checked:bg-[#f0db4e]"
/>
<span className="pl-2">Intermediate</span>
</label>
</div>
<div className="md:mb-2 text-[#2d2d32] font-medium hover:font-bold transition-all text-sm">
<label
htmlFor={`${
props.idFor ? props.idFor + "advanced" : "advanced"
}`}
className="w-full cursor-pointer items-center flex"
>
<input
type="radio"
id={`${
props.idFor ? props.idFor + "advanced" : "advanced"
}`}
name="priorExperiance"
value="advanced"
/>
<span className="pl-2">Advanced</span>
</label>
</div>
</fieldset>
</div>
<div className="mt-1">
<SubmitButton {...submitButton} />
</div>
</div>
</form>
)
}
the code above results in the the following ui
then when we submit the form it will trigger the server action. and while the asynchronous task is running the state of pending will be true and react will render the loadingSpinner component
const { data} = useFormStatus();
data*property that gets retured from the useFormStatus hook has information about the data being submitted.
for the example we demonstated above the
const { data } = useFormStatus();
console.log(data) // will result in the formdata being submitted
so data now has access to firstName, lastName , email ...etc fields that we are capturing data for.
const { meathod} = useFormStatus();
console.log(meathod) // GET (unless otherwise specified)
meathod*has information about the HTTP methods (GET, POST, PUT, PATCH, DELETE) about the type of request being submitted. by default the request is a GET request
const { action} = useFormStatus();
action*is the refrence to the server action function passes to the form.
for the code example used above the action is
const { action} = useFormStatus();
<form action={serverAction}>
// some fileds
<SubmitButton {...submitButton} />
</form>
console.log(action) // is refrence to `serverAction` action prop of the form
some things we need to be aware of when using this hook is