How to use React.forwardRef() in in functional component react js

Viewed 13

I am creating a reusable form control in react using useForm hook. Now I need to use React.forwardRef to pass the ref. But I am getting error "Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?". [![enter image description here][1]][1] Looks like I am using it wrong.

const Form = ({template}: Template) => {
    console.log('tempalte', template)
    const {title, fields, ...otherProps} = template;
    const {register, handleSubmit} =  useForm();

   const onSubmit=(values:any)=>console.log('values', values);
   const renderFields:React.ForwardedRef<(Fields[])> =(fields)=>{//error in this line
    return fields?.map((field)=>{
        let {name, type, label} = field;
        return (
          <div key={name}>
             <TextfieldWrapper type={type}  name={name}  id={name} ref={register} />
          </div>
        )
      })
   }

  return (
    <div>
      <form onSubmit={handleSubmit(onSubmit)}>
        <h4>{title}</h4>
             <> {renderFields(fields)}</>
              <button type='submit' className='btn'>Submit</button>
        </form>
    </div>
  )
}

export type Fields={
    name: string,
    label?: string,
    type?: string,
    id?: string,
    ref?:any,
    // register:UseFormRegister<IFormValues>;
    // register: ReturnType<UseFormRegister<IFormValues>
}

export type Template = {
    template:{
        fields: Fields[],
        title?: string,
        onSubmit?:()=>void
    }
    // ref?:any;
    onSubmit?:()=>void,
    children?: React.ReactNode,
}

const TextfieldWrapper = ({name, type,  ...otherProps} : Fields) => {
//   const [field, mata] = useField(name);
    console.log('wrapper', name, type, {...otherProps});

  const configTextfield: any = {
    name,
    ...otherProps,
    fullWidth: true,
    variant: 'outlined'
  };



  return (
    <TextField {...configTextfield} />
  );
};

export default TextfieldWrapper; [1]: https://i.stack.imgur.com/booDh.png

1 Answers

You need to use forwardRef where you implement TextFieldWrapper, not where you use it. So if that implementation currently looks like this:

const TextFieldWrapper = (props: TextFieldWrapperProps) => {
  //  Obviously, your implementation will be more complex
  return (
    <div>
      <input type={props.type}/>
    </div>
  )
}

And you want that if a ref is passed to TextFieldWrapper it gets forwarded to that input element, you'll do:

const TextFieldWrapper = React.forwardRef<HTMLInputElement, TextFieldWrapperProps>(
  (props, ref) => {
    return (
      <div>
        <input ref={ref} type={props.type}/>
      </div>
    )
  }
);
Related