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
Avatar
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()
View full answer

25 Replies

Avatar
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()
Answer
Avatar
Korat
@Tomistoma Do you think that calling <FormProvider> on every form even though its not needed sometimes have performance issues ?
Avatar
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.
Avatar
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
Avatar
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.
Avatar
Korat
yeah but we won't be able to use the radix's anatomy of Form
Avatar
Tomistoma
I wouldn't worry about it. Shadcn's form is entirely RHF. Even though Radix has one, shadcn doesn't use it.
Avatar
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
Avatar
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
Avatar
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 ?
Avatar
Tomistoma
It won't. My bad I didn't realize it was wrapped in a provider.
Avatar
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
Avatar
Tomistoma
You can refactor the code inside to create your own to just use the Controller and remove any references to the context
Avatar
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
Avatar
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
Avatar
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
Avatar
Tomistoma
Yeah, I've also used RHF with MUI for forms with and without FormProvider. I never had an issue for forms with FormProvider.
Avatar
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