I'm using version 7 of the library, but I'm having a problem in two situations:
I need to dynamically render the Controller, because the form is assembled with data from the backend response;
I'm trying to create a specific component for the Controller and reuse it inside forms;
I'm trying to do it this way, but it's probably wrong:
ControllerComponent
import { Control, Controller, FieldValues } from 'react-hook-form';
import Select from '../../core/Select';
interface IProps {
name: string;
tabIndex: string;
// eslint-disable-next-line @typescript-eslint/ban-types
control: Control<FieldValues, object>;
isDisabled: boolean;
placeholder: string;
options: [
{
label: string;
value: string;
}
];
}
const SelectControllerForm = ({ name, control, ...props }: IProps) => (
<Controller
name={name}
control={control}
render={({ field, fieldState: { error } }) => (
<Select required={true} isClearable={true} error={!!error} {...field} {...props} />
)}
/>
);
FormComponent
const { register, control } = useForm({
resolver: yupResolver(schema),
});
const { fields, append, prepend, remove, swap, move, insert } = useFieldArray({
control, // control props comes from useForm (optional: if you are using FormContext)
name: 'test', // unique name for your Field Array
keyName: 'key', //default to "id", you can change the key name
});
const onSubmit = (data: any) => {
console.log('AQUI');
console.log(data);
};
useEffect(() => {
append({ firstName: 'bill', lastName: 'luo' });
append({ a: 'oi', b: 'aq' });
}, []);
return (
<form onSubmit={}>
{fields.map((field, index) => (
<SelectControllerForm
key={field.key}
name={index.toString()}
control={control}
tabIndex='-1'
isDisabled={false}
placeholder='ae'
options={[
{
label: 'string',
value: 'string',
},
]}
/>
))}
</form>
)
It's updating the screen all the time and giving REF error:
There are couple of problems with your code:
1- You can not call actions one after another. Actions need to be triggered per render, so you need to change your apped
like this:
useEffect(() => {
append([
{ value: 'a', label: 'a' },
{ value: 'b', label: 'b' },
]);
}, []);
2- react-hook-form
does not support flat field array, so you need to set the name of fields as nested field of arrayField, like this:
{fields.map((field, index) => (
<SelectControllerForm
key={field.key}
name={`test.${index.toString()}`}
control={control}
...
/>
))}
I hope theses changes solve your problem, if it doesn't helpe, it will be better to include your code on a Code sandbox
example and link it here.