react-hook-form: issue: Select value is not aligning with dynamic options based on other field values
Version Number
7.33.1
Codesandbox/Expo snack
https://codesandbox.io/s/react-hook-form-csb-m5t03g?file=/src/ReactHookForm.tsx
Steps to reproduce
I tried condensing this down as much as possible. The original functionality has buttons to increment or decrement single episodes, but I believe this is all under the same issue and can be demonstrated solely by the finish button.
- Select any season other than the last
- Click on ‘finish’
You will see that both the episode value and episode options are correct, but the select is not displaying the correct value. If you are already on the final season, then clicking ‘finish’ will immediately show the correct value. I know this is happening because we are transitioning from a season with less possible episodes than the one that is being set. If the final season has less than or equal to the number of episode of the current season, then the finish button works properly.
Expected behaviour
The <select> for progress_episode gets its possible values from watch('progress_season') to determine the episode count. When using setValue to update the inputs outside of the select element, watch seems to display the correct values, but the current selection on the input doesn’t update.
What browsers are you seeing the problem on?
No response
Relevant log output
No response
Code of Conduct
- I agree to follow this project’s Code of Conduct
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 17 (10 by maintainers)
A working CSB
I didn’t know that either, that is really helpful. I use
setValueAs: (v) => parseInt(v)elsewhere so am familiar with the callback version. I will switch to something like that. Thank you!This makes a lot more sense. Thank you for all your help!
I also want to say how much I love this library. It is so powerful, thank you!
If you’ve never used the
ControllerAPI before, make note of what thefieldobject is and that it has thevalueprop which you can spread into an input along with the other props you can find returned from theregistermethod call. Butregisternever returnsvalue, since it’s designed to handle the uncontrolled componentsThe concept of controlled vs uncontrolled inputs is outside RHF and is about where the input’s value is stored.
You can better learn about this concept and the RHF
ControllerAPI yourself, but theTLDR;is: controlled components are “controlled” with a value from outside, like React’sstate, so, they’re being “fed” the value into theirvalueprop or whatever. Uncontrolled components on the other hand, are the source of truth of their value, like a plain HTML input without JS; RHF listens for it’sonChangeevent and “makes note” of it’s value, but never “tells” the input what the value is.@Moshyfawn this is super helpful, thank you! I have never worked with Controlled components with React hook Form before so this will be a first for me. I will have to read up on them to understand what is going on better. But your example totally works so that’s awesome!
I’d say, the
progress_episodeinput should be controlled instead, because it’s more of a React component life-cycle issue at this point.Here’s a very crude example; you can optimize it however you want, but the idea is to “control” the input’s value outside of it, instead of using the uncontrolled API (
register) where the input’s value source of truth is inside the input and “hoping” value’s gonna be updated in time after the “outside” updateExactly. If the final season has an episode number that is equal to or less than the season you are currently in, then the button performs correctly.
I have to dynamically update the episode options based on which season is selected so I’m not sure how else to make sure that always renders before the value is set.
thanks, @Moshyfawn got it thanks. coupld issues:
valueAsNumberis not applicable forselect6hence set select13is not going to workThanks for the detailed issue report and condensed csb (i can see the effort), would you mind sharing a video on the actual issue as well? It probably would be easier to spot the issues.
also curious about the following code maybe the root cause:
could you also double-check if the watch itself returns the expected results for you?