Panchakshari Puranmatt
Panchakshari Puranmatt

Reputation: 333

Using react-hook-form's ref is throwing errors in the console if I use a custom component instead of normal HTML5 input tag

I am trying react-hook-form for the first time today (was using formik till now). I have followed everything according to the docs. Still getting errors saying "Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?" and also when I click on submit, there is no value being shown-up. 'HookFormControl' is a custom input element, which has been imported.

import { useForm } from 'react-hook-form'
import HookFormControl from '../forms/HookFormControl'

const { register, handleSubmit, errors, reset } = useForm()
const onSubmit = submittedData => { console.log('submittedData = ', submittedData) }

<form onSubmit={handleSubmit(onSubmit)}>
 <div className='row'>
  <div className='col-12'>
    <HookFormControl type='text' label='Site Name *' name='site' ref={register({required: true})} />
  </div>
 </div>

<div className='row'>
  <div className='col-12'>
    <button type='submit'>Create</button>
  </div>
 </div>
</form>

Upvotes: 1

Views: 6032

Answers (1)

Bill
Bill

Reputation: 19248

  1. make sure that HookFormControl component does expose input's ref

https://react-hook-form.com/get-started#Integratinganexistingform

// you can use React.forwardRef to pass the ref too
const Select = React.forwardRef(({ label }, ref) => ( 
  <>
    <label>{label}</label>
    <select name={label} ref={ref}>
      <option value="20">20</option>
      <option value="30">30</option>
    </select>
  </>
));
  1. you can use Controller to wrap your controlled component

https://react-hook-form.com/get-started#IntegratingControlledInputs

import React from "react";
import { useForm, Controller } from "react-hook-form";
import ReactSelect from "react-select";
import { TextField, Checkbox } from "@material-ui/core";

function App() {
  const methods = useForm();
  const { handleSubmit, control, reset } = methods;
  const onSubmit = data => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      {/* Option 1: pass a component to the Controller. */}
      <Controller as={TextField} name="TextField" control={control} defaultValue="" />
      
      {/* Option 2: use render props to assign events and value */}
      <Controller
        name="MyCheckbox"
        control={control}
        defaultValue={false}
        rules={{ required: true }}
        render={props =>
          <Checkbox
            onChange={e => props.onChange(e.target.checked)}
            checked={props.value}
          />
        } // props contains: onChange, onBlur and value
      />
    </form>
  );
}

Upvotes: 3

Related Questions