Reputation: 1371
I have two components, where selectBirthMonth depends on SelectBirthYear. Which is why I use useEffect, to watch the selectedYear change, so that I can change selectedMonth in case it is needed.
So in controller context my components look the following
<Controller
control={control}
name="selectedBirthYear"
defaultValue={years[0]}
render={({ field }) => (
<SelectBirthYear
field={field}
years={years}
value={selectedYear}
defaultValue={selectedYear}
onChange={useEffect(() => {setSelectedYear(field.value)})}
/>
)}
/>
</div>
and ...
<Controller
control={control}
name="selectedBirthMonth"
defaultValue={months[0]}
render={({ field }) => (
<SelectBirthMonth
field={field}
startYear={startYear}
selectedYear={selectedYear}
months={months}
value={selectedMonth}
defaultValue={selectedMonth}
reducedMonths={reducedMonths}
onChange={useEffect(() => setSelectedMonth(field.value))}
/>
)}
/>
SelectBirthMonth totally ignored the following code though:
const [selectedMonth, setSelectedMonth] = useState(months[0]);
const watchYearChange = () => {
if(Number(selectedYear.name) == startYear){
setSelectedMonth(reducedMonths[reducedMonths.length - 1]);
}
};
useEffect(() => watchYearChange(), [selectedYear]);
Meaning, no matter, which year is chosen, the month won't react. What do I miss?
Upvotes: 0
Views: 884
Reputation: 6949
I would recommend using a small date library like date-fns
to handle date related things. It's a great package, here are the docs for it. Also it can handle i18n for you if this should be a requirement in the future.
I used it in the below CodeSandbox and also corrected a few things:
Upvotes: 1
Reputation: 1371
The answer is way too easy, to be working, but it does. Several times I've been reading this post here How to change React-Hook-Form defaultValue with useEffect()?, but could't really understand, where and how do I use setValue. As I assumed, the value of my select just wasn't changing, even though I was watching the sibling state change.
So I put the setValue into the useEffect hook and the rest stayed the same:
const monthSelect = (data) => {
setSelectedMonth(months[data.id - 1]);
};
const watchYearChange = () => {
if(Number(selectedYear.name) == startYear){
setSelectedMonth(lastAvaliableMonth)
}
};
useEffect(() => setValue('selectedBirthMonth', lastAvaliableMonth), [selectedYear]);
Here are two siblings just in case:
<Controller
control={control}
name="selectedBirthYear"
defaultValue={years[0]}
render={({ field }) => (
<SelectBirthYear
field={field}
years={years}
value={selectedYear}
defaultValue={selectedYear}
onChange={useEffect(() => {setSelectedYear(field.value)})}
/>
)}
/>
... and
<Controller
control={control}
name="selectedBirthMonth"
defaultValue={selectedMonth}
render={({ field }) => (
< SelectBirthMonth
field={field}
startYear={startYear}
selectedYear={selectedYear}
months={months}
value={selectedMonth}
reducedMonths={reducedMonths}
onChange={useEffect(() => monthSelect(field.value)), [selectedMonth]}/>
)}
/>
If this solution somehow is not good, please let me know in the comments. I am a total beginner.
Upvotes: 0