I have a multi-step form (react-hook-form) in Next.js. The onSubmit() event lives in a component called from the layout, and I’d like to be able to add a spinner and disable the submit button. How can I know on the page when onSubmit has been called?
layout.tsx –
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<div>
<Sidebar />
<Provider>{children}</Provider>
</div>
);
}
Provider.tsx
export default function Provider({ children }: FormProviderProps) {
const onMyFormSubmit = async (data: FormTypes) => {
await createStory(data);
}
return (
<FormProvider {...methods}>
{/* <form onSubmit={methods.handleSubmit(onSubmit)} className="flex w-full"> */}
<form onSubmit={methods.handleSubmit((data) => onMyFormSubmit(data))} className="flex w-full">
{children}
</form>
</FormProvider>
);
}
interface FormProviderProps {
children: React.ReactNode;
}
page.tsx –
export default function SummaryPage() {
return (
<div>
<FormWrapper heading="Finishing up" >
<div className="flex flex-col bg-alabaster rounded-lg px-4 lg:px-6 mt-6 w-full shrink-0">
<div className="flex items-center justify-between pt-4 pb-3 lg:pb-5">
<button
type="submit"
disabled={prop I need from onSubmit event}
className=".."
>
Submit story
</button>
<div className={prop I need from onSubmit event? undefined : 'hidden'}>
<Spinner height="80" width="80" color="#713F12" />
</div>
</div>
</div>
</div>
);
}
I’m new to Next and react, so would really appreciate guidance here.
I’ve looked at react context, but as far as I understand it, it doesn’t seem dynamic (once an object has passed, it doesn’t update)
2
Answers
I ended up using the
isSubmitting
state anduseEffect
to capture when it changes.I use
useEffect
instead ofisSubmitting
directly since it quickly reverts back to false once submission has been completedYou can pass a callback function as props and use it to notify a parent component
then you’d toggle the disableSubmit in your parent component before and after recieving the reponse which will send the buttons ‘disableSubmit’ state back down
disclaimer:
this is a gist that should come close hopefully answer your question. (you may chose to apply the suggestion to the onsubmit of the form over attaching it directly to the button as done above)
But would recommend simplifying it by having the form component itself handle the async request.
if multiple components need to know then implementing a global state provider (same idea as the form provider just wrap everything from index.js/ts), that can toggle a "loading" state so any component that needs to know about can react to it directly.
instead of bubbling callbacks up and down through each component as it gets messy fast. just a imo; if I had to send a callback up through multiple components might reconsider the component architecture.