I’m trying to use the new useFormStatus()
hook on a react + next.js project, but it’s not working as I expect:
import { useFormStatus } from "react-dom";
type SurveyResultProps = {
answers: Record<string, Answer>
}
const SurveyResult: React.FC<SurveyResultProps> = ({ answers }: SurveyResultProps) => {
const [resultText, setResultText] = useState('');
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const text = await getResultText(answers);
setResultText(text);
};
function Submit() {
const asdf = useFormStatus();
console.log(asdf);
const { pending } = asdf;
return <Button type="submit" disabled={pending} text={pending ? "Submitting..." : "Submit"} />
}
return <div>
<form onSubmit={handleSubmit}>
<Submit />
</form>
{resultText && (
<pre>{resultText}</pre>
)}
</div>;
}
The server action works and the resultText
is correctly displayed on the page. However…
- the hook always says the form isn’t pending
- the button never disables, and
- the button text never changes from
Submit
toSubmitting...
Here’s console.log
output:
{pending: false, data: null, method: null, action: null}
{pending: false, data: null, method: null, action: null}
{pending: false, data: null, method: null, action: null}
{pending: false, data: null, method: null, action: null}
I see in the docs this hook is marked as a "canary" feature, is there anything else I need to do to opt into it? Or is something wrong with my implementation?
2
Answers
You are defining an
onSubmit
handler that also callsevent.preventDefault()
, so the form submit event is cancelled.If you look at usage examples for
useFormStatus
in the React documentation, none of them are cancelling the form’s submit event. Specifically, from the React documentation:So you can update your code to not use
event.preventDefault
or theonSubmit
handler and instead pass a reference to anaction
that wrapsgetResultText
:You can also define the
action
inline:Most simple solution would be to use separate the submit component in another file and make it a client component using ‘use client’ hook.