'How to pass initial values to child components through react-hook-forms
I'm trying to pass initial values to a form (like for instance after calling an API and filling up the form). My concern is when filling values to child components (YearSelect). The code below works but I have no idea if this is the best solution using react-hook-forms.
import { useEffect } from 'react';
import { useForm } from 'react-hook-form';
function YearSelect(props) {
useEffect(() => {
props.setValue('year', props.data);
});
return (
<select name="year" {...props.register('year')}>
<option value="">---</option>
<option value="2021">2021</option>
<option value="2022">2022</option>
</select>
)
}
function App() {
const { register, handleSubmit, watch, formState: { errors }, setValue, getValues } = useForm();
let year = 0;
useEffect(() => {
setValue('title', 'HEY');
setValue('year', 2021);
year = getValues('year');
console.log(year);
});
const onSubmit = data => {
alert(1);
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
Title: <input name="title" {...register('title')}/><br/>
Year: <YearSelect name="year" register={register} data={year} setValue={setValue}/>
<button type="submit">Save</button>
</form>
);
}
export default App;
Solution 1:[1]
let year = 0;
This is not a react hook based variable. When you assign value to it, the component will not track it and won't rerender itself. Instead, use
const [year, setYear] = useState(0);
//And in useEffect,
setYear(getValues('year'))
Apart from that, all other parts of the component seem to be fine.
Solution 2:[2]
I think I found another option. Using FormProvider and UseFormContext
import { useEffect, useState } from 'react';
import { useForm, FormProvider, useFormContext } from 'react-hook-form';
function YearSelect(props) {
const { register, setValue } = useFormContext(); // retrieve all hook methods
useEffect(() => {
setValue('year', props.data);
});
return (
<select name="year" {...register('year')}>
<option value="">---</option>
<option value="2021">2021</option>
<option value="2022">2022</option>
</select>
)
}
function App() {
const methods = useForm();
const [year, setYear] = useState(0);
useEffect(() => {
methods.setValue('title', 'HEY');
methods.setValue('year', 2021);
setYear(methods.getValues('year'));
}, []);
const onSubmit = data => {
alert(1);
}
return (
<FormProvider {...methods}>
<form onSubmit={methods.handleSubmit(onSubmit)}>
Title: <input name="title" {...methods.register('title')}/><br/>
Year: <YearSelect name="year" data={year}/>
<button type="submit">Save</button>
</form>
</FormProvider>
);
}
export default App;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | S K R |
| Solution 2 | Ruben |
