Jeewantha Lahiru
Jeewantha Lahiru

Reputation: 394

Return the value of React-Select using React-Hook-Form with Typescript

I am using react-hook-form controller with react-select. I am using React with Typescript. I can get the value of selected when submit, but it returns the both value and label from options array as an object.How can I return value only? here is the code,

const { handleSubmit, control, formState:{errors}} = useForm<IAddProductForm>();

const handleOnSubmit = (data:IAddProductForm) => {
        console.log(data);
    }

const categoryOptions = [
        {value:"Grocery", label:"Grocery"},
        {value:"Pharmacy", label:"Pharmacy"},
        {value:"Electronic", label:"Electronic"},
        {value:"Food", label:"Food"},
    ];

return(
        <React.Fragment>
           <Form onSubmit={handleSubmit(handleOnSubmit)}>
               <Controller
                   control={control}
                   render={({field:{onChange, value, name, ref}}) => (
                        <Select
                           inputRef={ref}
                           value={categoryOptions.find(c => c.value === value)}
                           options={categoryOptions}
                           onChange={onChange}
                        />
                   )}
                   name={"category"}
                />
               <Button type={"submit"}>submit</Button>
            </Form>
        </React.Fragment>
);

this code returns category: {value: "Grocery", label: "Grocery"} this if I select Grocery and submit it. but I need to return category:"Grocery" like this.

Upvotes: 2

Views: 14391

Answers (1)

jean182
jean182

Reputation: 3505

Hey it is actually a matter of changing your on change function and to use the value like this:

interface IAddProductForm {
  category: string;
}

interface ICategory {
  value: string;
  label: string;
}

function YourComp() {
const { handleSubmit, control, formState:{errors}} = useForm<IAddProductForm>();

    const handleOnSubmit = (data:IAddProductForm) => {
        console.log(data);
    }

    const categoryOptions: ICategory[] = [
        {value:"Grocery", label:"Grocery"},
        {value:"Pharmacy", label:"Pharmacy"},
        {value:"Electronic", label:"Electronic"},
        {value:"Food", label:"Food"},
    ];

    return(
        <React.Fragment>
           <Form onSubmit={handleSubmit(handleOnSubmit)}>
               <Controller
                   control={control}
                   render={({ field: { onChange, value, name, ref } }) => (
                     <Select
                      inputRef={ref}
                      value={categoryOptions.find((c) => c.value === value)}
                      name={name}
                      options={categoryOptions}
                      onChange={(selectedOption: ICategory) => {
                       onChange(selectedOption.value);
                      }}
                     />
                   )}
                   name={"category"}
                />
               <Button type={"submit"}>submit</Button>
            </Form>
        </React.Fragment>
);
}

If you take a look closely I just add some types for the categoryOptions const to be able to type the onChange function and modify it to look like this.

onChange={(selectedOption: ICategory) => {
 onChange(selectedOption.value);
}}

Basically the value received is the full object and you just need to extract the value of it in and pass it to the controller onChange function. Also you're right by passing the value and using the array find to match the object and make the select work properly.

If you submit that you should be able to see that the formData returns a category with the string value only, not the object.

Here's a working sandbox: https://codesandbox.io/s/boring-blackwell-qoer1

Upvotes: 7

Related Questions