Next.js Discord

Discord Forum

How to split Shadcn form with react-hook-form in to multiple smaller form components

Answered
Rhinelander posted this in #help-forum
Open in Discord
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 Brokenwind
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()
View full answer

25 Replies

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()
Answer
Korat
@Brokenwind Do you think that calling <FormProvider> on every form even though its not needed sometimes have performance issues ?
@Korat <@709274554261831761> Do you think that calling <FormProvider> on every form even though its not needed sometimes have performance issues ?
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.
But shadcn doesnt worry about this, why should we hahaha
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
@Korat yeah but we won't be able to use the radix's anatomy of Form
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

<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
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 ?
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
@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
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
@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
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
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
@Korat 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 /
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