couds / react-bulma-components

React components for Bulma framework
MIT License
1.2k stars 126 forks source link

Input ref failure #343

Closed martinlehoux closed 3 years ago

martinlehoux commented 3 years ago

Describe the bug

This is a warning from React. I can't exactly say what it may cause.

I am using react-hook-form@7.7.1, and I have this warning when I register my Input.

My Select does not work: when I select an option, it instantly switches back to the default one. It may or not be related to this issue.

To Reproduce

  1. Create a controlled input and select
    
    const { register, handleSubmit } = useForm()

<Input {...register('name')} /> <Select {...register('companyId')}>

{companies?.map(c => (
  <option key={c.id} value={c.id}>{c.name}</option>
))}

2. Open dev tools
3. Select an option in the select

**Expected behavior**
Being able to control my Select.

**Trace**

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



**Versions**
- `react-bulma-components`: 4.0.6
- `bulma`: 0.9.2
- `react`: 17.0.2
- Browser: Firefox 89.0 (Ubuntu), Chrome 91.0 (Android 11)
couds commented 3 years ago

Hi Martin. To add a ref you need to pass a custom prop named domRef (instead of ref)

You can check it here https://github.com/couds/react-bulma-components#adding-ref-to-a-component

couds commented 3 years ago

Hi @martinlehoux

You could also use it like this

const { register, handleSubmit } = useForm()

const { ref: nameRef, ...nameProps} = register('name')
const { ref: companyIdRef, ...companyIdProps} = register('companyId')

<Input {...nameProps)} domRef={nameRef} />
<Select {...companyIdProps} domRef={companyIdRef}>
  <option value=''>Select company</option>
    {companies?.map(c => (
      <option key={c.id} value={c.id}>{c.name}</option>
    ))}
</Select>
martinlehoux commented 3 years ago

Thanks for the tip @couds !

ksdme commented 1 year ago

A simpler solution that I ended up using is a utility function.

export function bulmaize<T extends { ref: any }>(registration: T): Omit<T, "ref"> | { domRef: any } {
  const {
    ref: domRef,
    ...others
  } = registration

  return {
    ...others,
    domRef,
  }
}

And register using {...bulmaize(form.register("email", { required: false }))}.