Error when submitting dependent select components with ShadCN/react-hook-form. How to use custom change functions

I want to create two Select components using ShadCN. I want these selects to have a dependency between each other.

This means that after a value is selected for categories, then the select of subcategories is populated with the filtered data accordingly.

This step is working fine.

However, when I click on submit the form, it is as if the category was an empty value and I believe it is because I am using a custom handle function in the onValueChange event instead of using the field.onChange.

I still haven’t gotten the hang of using the Form components and all its intricacies so I don’t understand how I can use my own change function to handle the events or even how I could have these components as reusable components and avoid DRY.

#... imports

export const TransactionForm = () => {
  const [selectedCategory, setSelectedCategory] = useState<string>("");
  const [selectedSubcategory, setSelectedSubcategory] = useState<string>("");
  const [filteredSubcategories, setFilteredSubcategories] = useState<string[]>(
    []
  );

  const form = useForm<z.infer<typeof TransactionSchema>>({
    resolver: zodResolver(TransactionSchema),
    defaultValues: {
      category: "",
      subcategory: "",
    },
  });

  const categories = [...dummyData.categories].map((item) => item.name);

  const onSubmit = (values: z.infer<typeof TransactionSchema>) => {
    console.log(values);
  };

  const handleCategoryChange = (category: string) => {
    setSelectedCategory(category);
    setSelectedSubcategory("");
    console.log(category);
    const categoryData = dummyData.categories.find(
      (item) => item.name === category
    );
    if (categoryData) {
      setFilteredSubcategories(categoryData.subcategories);
    } else {
      setFilteredSubcategories([]);
    }
  };

  const handleSubcategoryChange = (subcategory: string) => {
    setSelectedSubcategory(subcategory);
  };

  return (

      <Form {...form}>
        <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
          <div className="space-y-4">
            <FormField
              control={form.control}
              name="category"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Category:</FormLabel>
                  <Select
                    onValueChange={(value) => handleCategoryChange(value)}
                    defaultValue={field.value}
                  >
                    <FormControl>
                      <SelectTrigger className="w-[180px] h-[40px]">
                        <SelectValue placeholder="Category" />
                      </SelectTrigger>
                    </FormControl>
                    <SelectContent className="bg-white">
                      <SelectGroup>
                        <SelectLabel>Category</SelectLabel>
                        {categories.map((option, index) => (
                          <SelectItem key={index} value={option}>
                            {option}
                          </SelectItem>
                        ))}
                      </SelectGroup>
                    </SelectContent>
                  </Select>
                </FormItem>
              )}
            />

            <FormField
              control={form.control}
              name="subcategory"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Subcategory:</FormLabel>
                  <Select
                    onValueChange={field.onChange}
                    defaultValue={field.value}
                    {...field}
                  >
                    <FormControl>
                      <SelectTrigger className="w-[180px] h-[40px]">
                        <SelectValue placeholder="Subcategory" />
                      </SelectTrigger>
                    </FormControl>
                    <SelectContent className="bg-white">
                      <SelectGroup>
                        <SelectLabel>Subcategory</SelectLabel>
                        {filteredSubcategories.map((option, index) => (
                          <SelectItem key={index} value={option}>
                            {option}
                          </SelectItem>
                        ))}
                      </SelectGroup>
                    </SelectContent>
                  </Select>
                </FormItem>
              )}
            />
          </div>
          <Button type="submit" className="w-full">
            Save
          </Button>
        </form>
      </Form>
    </CardWrapper>
  );
};