Why I cant register two components of the same name using React Hook Form?

Viewed 29

I am using useForm hook produced by React Hook Form library. Because of the UI library that I use I am forced to create custom radio buttons. My problem is that even i have a type in interface that defines the form when I try to register two components of same name I am getting an warning that says:

'Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

Check the render method of `NewForm`.
    at ToggleButton (http://localhost:3000/static/js/main.chunk.js:1236:23)'

Here is the interface and type:

interface FormInput {
  dynamicFieldTitle: string;
  formTitle: string;
  tokenType: TokenType;
  tokenAddress: string;
  tokenId: string;
  expirationDate: string;
}

type TokenType = "ERC1155" | "ERC721";

And here is the JSX code:

    <ToggleButton
      {...register("tokenType")}
      onClick={toggleButtonHandler}
      position="left"
      selected={!isERC1155}
    >
      ERC721
    </ToggleButton>
    <ToggleButton
      {...register("tokenType")}
      onClick={toggleButtonHandler}
      position="right"
      selected={isERC1155}
    >
      ERC1155
    </ToggleButton>
1 Answers

register method allows you to register an input or select element. it returns some methods, one of which is ref. In React you can't pass ref to a function component. instead you have to wrap the function component in forwardRef. like this:

// not working, because ref is not assigned
<TextInput {...register('test')} />

const firstName = register('firstName', { required: true })
<TextInput
  onChange={firstName.onChange}
  onBlur={firstName.onBlur}
  inputRef={firstName.ref} // you can achieve the same for different ref name such as innerRef
/>

// correct way to forward input's ref
const Select = React.forwardRef(({ onChange, onBlur, name, label }, ref) => (
  <select name={name} ref={ref} onChange={onChange} onBlur={onBlur}>
    <option value="20">20</option>
    <option value="30">30</option>
  </select>
));
  • to work with custom component (e.g. UI library) React-hook-form recommends to use useController hook or Controller component.

  • if you want to manually register your custom component you will need to update the input value with setValue.e.g.

register('firstName', { required: true, min: 8 });

<TextInput onTextChange={(value) => setValue('lastChange', value))} />

you can follow the RHF document. https://react-hook-form.com/api/useform/register/

useController https://react-hook-form.com/api/usecontroller

Related