ui: Unable to reset the Select component with React Hook Form

Calling form.reset() (React Hook Form reset method) does not reset the value selected by the user in the Select.

Here’s my useForm hook usage:

const form = useForm<z.infer<typeof someSchema>>({
    resolver: zodResolver(someSchema),
})

Here’s my submit handler:

async function onSubmit(values: z.infer<typeof someSchema>) {
  form.reset()
}

Here’s my Select field:

<Form {...form}>
  <form
    onSubmit={form.handleSubmit(onSubmit)}
  >
    <FormField
      control={form.control}
      name="type"
      render={({ field }) => (
        <FormItem>
          <FormLabel>Type</FormLabel>
          <Select onValueChange={field.onChange} defaultValue={field.value}>
            <FormControl>
              <SelectTrigger>
                <SelectValue placeholder="Select something" />
              </SelectTrigger>
            </FormControl>
            <SelectContent>
              <SelectItem value="A">
                A
              </SelectItem>
              <SelectItem value="B">
                B
              </SelectItem>
            </SelectContent>
          </Select>
        </FormItem>
      )}
    />
    <Button type="submit">
       Submit
     </Button>
  </form>
</Form>

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Reactions: 7
  • Comments: 35

Most upvoted comments

Try using value instead of defaultValue

-<Select onValueChange={field.onChange} defaultValue={field.value}>
+<Select onValueChange={field.onChange} value={field.value}>

As a temporary workaround, I have modified the SelectTrigger to explicitly check the field.value. If it is not set, it displays your placeholder.

<FormItem>
  <FormLabel>Size</FormLabel>
  <Select
    onValueChange={field.onChange}
    defaultValue={field.value}
+   value={field.value}
  >
    <FormControl>
      <SelectTrigger>
+       {field.value ? <SelectValue placeholder="Select size" /> : "Select size"}
      </SelectTrigger>
    </FormControl>
    <SelectContent>
      <SelectGroup>
        <SelectLabel>Size</SelectLabel>
        <SelectItem value="small">
          Small
        </SelectItem>
        <SelectItem value="medium">
          Medium
        </SelectItem>
      </SelectGroup>
    </SelectContent>
  </Select>

You also need to add the value prop to the Select component, as @riyaadh-abrahams suggested, in order to clear the selection when calling form.reset().

Try using value instead of defaultValue


-<Select onValueChange={field.onChange} defaultValue={field.value}>

+<Select onValueChange={field.onChange} value={field.value}>

I have tried this and setting the defaultValues to undefined. When form.reset() is called, the <Select value={field.value}> doesn’t reset back to the original where the <SelectValue placeholder='Select a role'>.

Try setting it up like this

const form = useForm<z.infer<typeof someSchema>>({
    resolver: zodResolver(someSchema),
    defaultValues: {
        type: "A"
    }
})

If you want to have also unset state, so there is option A,B or not selected, you can make “type” nullable in your zod schema and set defaultValue to null.

Then just call reset() without providing any parameters if you want to reset whole form

I tried doing this and I does reset the values however it doesn’t the entered value on the input field resulting in something like this image

i think you need to pass defaulValues

form.reset(defaultValues)

react hook form reset has bug !

use form.reset, form can’t rerender select. so u can see it not working. but form.setValue can working and rerender.

and how to use it for 100% working

just like this

reset single form item

const onReset = (name: string) => form.setValue(name, "");

reset all form item

import { useFormContext, UseFormReturn } from "react-hook-form";

export const useReset = (form?: UseFormReturn<any>) => {
  const formctx = useFormContext();
  const { getValues, setValue } = form ?? formctx;
  const fields = Object.keys(getValues());
  fields.forEach((field) => setValue(field, ""));
};

As @joaom00 said, you need to upgrade to @radix-ui/react-select@2.0.0-rc.9. I got the desired behavior by setting the default value to "" and adding value={field.value} to the Select.

Is there a similar problem with Radio Group? I’m trying to use it in the exact way indicated:

<RadioGroup
    onValueChange={field.onChange}
    defaultValue={field.value}
    className="flex flex-col space-y-1"
>

And I’m having the problem that form.reset doesn’t reset this field

Hi @asafeclemente , you can change like that. change : defaultValue={field.value} -> value={field.value}

"use client";

import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { z } from "zod";

import { Button } from "@/components/ui/button";
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { toast } from "@/components/ui/use-toast";

const FormSchema = z.object({
  type: z.enum(['',"all", "mentions", "none"], {
    required_error: "You need to select a notification type.",
  }),
});

export default function HomePage() {
  const form = useForm<z.infer<typeof FormSchema>>({
    resolver: zodResolver(FormSchema),
    defaultValues: {
      type: "",
    },
  });

  function onSubmit(data: z.infer<typeof FormSchema>) {
    toast({
      title: "You submitted the following values:",
      description: (
        <pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
          <code className="text-white">{JSON.stringify(data, null, 2)}</code>
        </pre>
      ),
    });
  }

  return (
    <div className="flex justify-center">
      <Form {...form}>
        <form
          onSubmit={form.handleSubmit(onSubmit)}
          className="w-2/3 space-y-6"
        >
          <FormField
            control={form.control}
            name="type"
            render={({ field }) => (
              <FormItem className="space-y-3">
                <FormLabel>Notify me about...</FormLabel>
                <FormControl>
                  <RadioGroup
                    value={field.value}
                    onValueChange={field.onChange}
                    // defaultValue={field.value}
                    className="flex flex-col space-y-1"
                  >
                    <FormItem className="flex items-center space-x-3 space-y-0">
                      <FormControl>
                        <RadioGroupItem value="all" />
                      </FormControl>
                      <FormLabel className="font-normal">
                        All new messages
                      </FormLabel>
                    </FormItem>
                    <FormItem className="flex items-center space-x-3 space-y-0">
                      <FormControl>
                        <RadioGroupItem value="mentions" />
                      </FormControl>
                      <FormLabel className="font-normal">
                        Direct messages and mentions
                      </FormLabel>
                    </FormItem>
                    <FormItem className="flex items-center space-x-3 space-y-0">
                      <FormControl>
                        <RadioGroupItem value="none" />
                      </FormControl>
                      <FormLabel className="font-normal">Nothing</FormLabel>
                    </FormItem>
                  </RadioGroup>
                </FormControl>
                <FormMessage />
              </FormItem>
            )}
          />
          <div className="flex justify-start space-x-2">
            <Button type="submit">Submit</Button>
            <Button type="reset" onClick={() => form.reset()}>Reset</Button>
          </div>
        </form>
      </Form>
    </div>
  );
}

Is there a similar problem with Radio Group? I’m trying to use it in the exact way indicated:

<RadioGroup
    onValueChange={field.onChange}
    defaultValue={field.value}
    className="flex flex-col space-y-1"
>

And I’m having the problem that form.reset doesn’t reset this field

<FormField
  control={form.control}
  name='furniture'
  render={({ field }) => {
    return (
      <FormItem>
        <FormLabel>Nội thất</FormLabel>
        <Select
          onValueChange={(value) =>
            value && field.onChange(value)
          }
          value={field.value}
        >
          <FormControl>
            <SelectTrigger>
              <SelectValue />
            </SelectTrigger>
          </FormControl>
          <SelectContent>
            {Object.values(furniture).map((item) => (
              <SelectItem value={item.key} key={item.key}>
                {item.name}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      </FormItem>
    )
  }}
/>

I found the problem caused by the onValueChange event inside the form. Try to modify onChangeValue and use value instead of defaultValue

Hey guys, there is a bug in Radix if you want to reset the value and show the placeholder again. It was fixed in https://github.com/radix-ui/primitives/pull/2174 and you can reset to placeholder using "". For now, it’s only available on RC https://www.npmjs.com/package/@radix-ui/react-select?activeTab=versions