How to split Shadcn form with react-hook-form in to multiple smaller form components
Answered
Rhinelander posted this in #help-forum
RhinelanderOP
I know this can be done but what is the proper way of doing it - with context? should i just past down useForm? What should I do?
Answered by Tomistoma
Shadcn already utilizes the Form component with useContext and FormProvider. Just use the useFormContext on your child components then get the control.
const { control } = useFormContext()
const { control } = useFormContext()
25 Replies
Tomistoma
Shadcn already utilizes the Form component with useContext and FormProvider. Just use the useFormContext on your child components then get the control.
const { control } = useFormContext()
const { control } = useFormContext()
Answer
Korat
@Tomistoma Do you think that calling <FormProvider> on every form even though its not needed sometimes have performance issues ?
Tomistoma
I would say it impacts performance because under the hood, it uses createContext. Shadcn's Form component is just the FormProvider from RHF. But performance issues? I doubt it. The primary reason to use RHF is due to its perfromant handling of forms.
Even though you'd have FormProvider (in shadcn's Form) I don't think it will be the issue if you're having performance issues.
Even though you'd have FormProvider (in shadcn's Form) I don't think it will be the issue if you're having performance issues.
Korat
Yeah thats right, I just felt like it does due to Wrapping all the form inside a provider but I'm assuming if you are not calling the useFormContext inside a component, the performance stays the same / with or without it.
But shadcn doesnt worry about this, why should we hahaha
Tomistoma
Yeah, if you're using shadcn, just remove <Form> and it's just the form without FormProvider
I think it's too little to matter. There are many reasons to have performance issues as you can be using RHF the wrong way. I don't think using FormProvider is one of them.
Korat
yeah but we won't be able to use the radix's anatomy of Form
Tomistoma
I wouldn't worry about it. Shadcn's form is entirely RHF. Even though Radix has one, shadcn doesn't use it.
Korat
I like to make inputs reusable by using this anatomy
I make a custom component that receives the control and the name.
What I was thinking is
Why do I need FormProvider (<Form> component) when inside of it its only 2 inputs and no usage of formContext
But as you mentioned, we shouldnt be worried about that
<FormField
control={form.control}
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="shadcn" {...field} />
</FormControl>
<FormDescription>This is your public display name.</FormDescription>
<FormMessage />
</FormItem>
)}
/>
I make a custom component that receives the control and the name.
What I was thinking is
Why do I need FormProvider (<Form> component) when inside of it its only 2 inputs and no usage of formContext
But as you mentioned, we shouldnt be worried about that
Tomistoma
Yeah, if it bothers you, you can just remove <Form> but don't remove <form>. It's just RHF and I guarantee it'll work because I saw the inside of Shadcn's form
Korat
I am not sure about that, FormField relies on FormProvider
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="shadcn" {...field} />
</FormControl>
<FormDescription>This is your public display name.</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
You are saying this will work ?
Tomistoma
It won't. My bad I didn't realize it was wrapped in a provider.
Korat
Exactly, thats why I am saying that we are forced to use the provider always, but still don't think its a performance issue we should worry about
Tomistoma
You can refactor the code inside to create your own to just use the Controller and remove any references to the context
Korat
Yeah that could be a solution, I might need to check how to work that out lol
https://github.com/shadcn-ui/ui/discussions/1212
https://github.com/shadcn-ui/ui/discussions/1212
Tomistoma
I see, so it has performance issues if used alongside the DevTools.
I can create an alternative form that doesn't use the FormProvider. Check back for the codesandbox link later
I can create an alternative form that doesn't use the FormProvider. Check back for the codesandbox link later
Korat
not just alongside Devtools, but as you saw it triggers a rerender of the root whenever a state is updated.
I mean in the other hand it makes the dx soo much better otherwise if we didn't have a provider we would need to pass the error state manually /
There are tradeoffs with both approaches
Tomistoma
Yeah, I've also used RHF with MUI for forms with and without FormProvider. I never had an issue for forms with FormProvider.
Korat
Me neither, but I wish shadcn gave a thought on this too,
For now dx is more important than a slightly non noticable performance drop