Search code examples
reactjstypescriptref

Using single ref for multiple input fields in react typescript


I am trying to use the same ref for multiple input fields in for my form. But on logging it, the ref refers only to the first input field. Is there anyway I can use the same ref and use for different inputs?

import React, {FC, useEffect, useRef, useState} from 'react';
import { IFormProps } from '../../utils/Interfaces';
import 'react-phone-number-input/style.css'

const Form:FC<IFormProps> = ({formData, handleFormData, errors, handleValidate}) => {
  const inputField = React.useRef() as React.MutableRefObject<HTMLInputElement>;
  
  return (
    <form className='user-form'>
        <label>First Name</label>
        <input 
          type="text" 
          ref = {inputField}
          value={formData.firstName} 
          name="firstName" id="firstName" 
          onChange={(e) => handleFormData(e)} placeholder="Enter your first name"
          onFocus={() => console.log('focus')} 
          onBlur={() => handleValidate(inputField)}
          />
        <label>Last Name</label>
        <input 
            type="text" 
            value={formData.lastName} 
            name="lastName" id="lastName" 
            onChange={(e) => handleFormData(e)} 
            placeholder="Enter the last name"
            onBlur={() => handleValidate(inputField)}
            ref = {inputField}
        />
    </form>

  )
}

export default Form;

I am passing this information to the parent to handle validation. I am not sure how I can pass the same ref(inputField) as different input elements with its attributes.

I have tried doing this Use a single ref object across multiple input elements, but there is an error saying the following. I am aware its cause of typescript. But not sure how to handle it.

ref = {(el) => (inputField.current["firstName"] = el)}

Element implicitly has an 'any' type because expression of type '"firstName"' can't be used to index type 'HTMLInputElement'.
  Property 'firstName' does not exist on type 'HTMLInputElement'.

Solution

  • In typescript, most hooks are generic. You declare their type using <>. If you want to assign to properties firstName and lastName then declare them in your type. You will also need to initialize the object.

      const inputField = React.useRef<{
        firstName: HTMLInputElement;
        lastName: HTMLInputElement;
      }>({ firstName: null, lastName: null });
    
      return (
        <form className="user-form">
          <label>First Name</label>
          <input
            ref={(ref) => (inputField.current.firstName = ref)}
            ...
          />
          <label>Last Name</label>
          <input
            ref={(ref) => (inputField.current.lastName = ref)}
            ...
          />
        </form>
      );
    

    demo: https://stackblitz.com/edit/react-ts-zkc3nj?file=App.tsx