I have a form (codesandbox here) with 2 components:
- A select input for the language (e.g.: English, Spanish)
- A textfield where the user enters a text in the selected language
The default form data looks like this:
{
"greeting": {
"en-US": "Hello",
"es-ES": "Hola"
}
}
My initial idea was to have a single input and just change its registered name based on the language selected. This way, when I select es-ES
, react-hook-form should replace the input’s value with the spanish text, and update the es-ES
prop when the user edits the text. However, if you play with the codesandbox above, you’ll notice that the wrong prop is being used.
I did find a potential workaround, which is to wrap my input with RHF’s <Controller />
and override the onChange
and value
, but that would likely require a considerable effort to implement on my real project, as the input is already using the Controller internally.
Hence my question: is this the expected behaviour of the library? If so, how would you approach this UI instead?
>Solution :
This bug may be caused by ref approach react-hook-form and their render optimisations. If I were you, I pass key prop to Controller
for re-render.
<Controller
key={fieldName} // <-- add key prop depending fieldName
name={fieldName}
control={control}
render={({ field: { ref, ...fieldProps }, fieldState: { error } }) => (
<TextField
label={fieldName}
InputProps={{
endAdornment: <div><LanguagePicker value={locale} onChange={setLocale} /></div>
}}
variant="outlined"
inputRef={ref}
{...fieldProps}
/>
)}
/>
With this workaround, you are sure that the controller render again if the key changed.
Edit: I’m not sure but this code block from the library repo looks like the root cause of this issue. They create registerProps with ref and your dynamic fieldName can’t be updated in there.