1
votes

I am using react-select dropdown with react-hook-form library. I am calling an api to get defaultValue for react-select. Initially dropdown was not able to prepopulate the defaultValue. So i found a workaround for that and re render the whole JSX when i get data from api.

<form onSubmit={handleSubmit(saveData)}>
{!countryValue && (
      <Controller
        name="country"
        control={control}
        render={({ onChange, value, ref }) => (
          <Select
            options={country}
            value={country.find((c) => c.value === value)}
            onChange={(val) => onChange(val.value)}
          />
        )}
        rules={{ required: true }}
      />
    )}
    {countryValue && (
      <Controller
        name="country"
        control={control}
        render={({ onChange, value, ref }) => (
          <Select
            options={country}
            value={country.find((c) => c.value === value)}
            onChange={(val) => onChange(val.value)}
            defaultValue={country.find((c) => c.value === countryValue)}
          />
        )}
        rules={{ required: true }}
      />
    )}
{errors.country && <div>Field is rquired</div>}
    <button type="submit">Save</button>
  </form>

I put a condition on countryValue that when component get the value of countryValue it render the whole dropdown.

But when i submit the form with the same defaultValue hook form gives an error of country field as undefined.

I have created a sandbox for this. https://codesandbox.io/s/react-select-with-react-hook-form-sc2xz

How can solve this issue. Is their any workaround.

2
can you post your expected output and explain a little more about what are you trying to do? - akhtarvahid
@akhtarvahid I want to set the defaultValue of the dropdown to india when api call is complete. And want to get only the value of the dropdwon when user submit the form. - rajatgalav

2 Answers

1
votes

I think that instead of recreating a new component to give it a default value, you should set the value on the existing component directly when you have it.

For that you can use setValue which you get from useForm() returned object.

Here is that part of the code:

  const { handleSubmit, control, errors, setValue } = useForm();

  useEffect(() => {
    setTimeout(() => {
      setValue("country", "India");
    }, 2000);
  }, [setValue]);

And here is the codesandbox.

0
votes

a great question, but it looks like you're doing it a little bit messy, you're passing the countries object to Select component and you're filtering it again in the value and onChange props (Why, i can't figure out?),

first you need to define a defaultValue for your Select component, but you cannot use both (defaultValue and value) in the same place, to do that use the Controller to set a default value for you you have already defined in countryValue state:

import "./styles.css";
import Select from "react-select";
import { useForm, Controller } from "react-hook-form";
import { useEffect, useState } from "react";

let country = [
  { label: "Bangladesh", value: "Bangladesh" },
  { label: "India", value: "India" },
  { label: "China", value: "China" },
  { label: "Finland", value: "Finland" }
];

export default function App() {
  const [countryValue, setCountryValue] = useState({
    label: "India",
    value: "India"
  });
  const { handleSubmit, control, errors } = useForm();

  useEffect(() => {
    setTimeout(() => {
      setCountryValue("India");
    }, 2000);
  }, []);

  useEffect(() => {
    console.log("errors", errors);
  }, [errors]);

  const saveData = (form_data) => {
    console.log("form_data", form_data);
  };

  return (
    <div className="App">
      <form onSubmit={handleSubmit(saveData)}>
        <Controller
          name="country"
          control={control}
          defaultValue={countryValue}
          render={({ onChange, value, ref }) => (
            <Select
              options={country}
              value={value}
              onChange={(val) => onChange(val)}
            />
          )}
          rules={{ required: true }}
        />

        {errors.country && <div>Field is rquired</div>}
        <button type="submit">Save</button>
      </form>
    </div>
  );
}