forwardRef and useImperativeHandle to access child components

Last updated : Jul 30, 2023 12:00 AM

1. Overview

useImparetiveHandler combined with forwardRef allows us to take control over child components' input elements. This tutorial explains how to use forwardRef and useImparetiveHandler to expose components dom elements to parent components or HOC (higher-order components)

2. forwardRef vs useImperativeHandle

forwardRef allows you to pass ref objects from parent components to child components, allowing you to access child components dom element. useImperativeHandle allows you to modify the ref object passed to the useImperativeHandle hook.

  • useImperativeHandle allows you to customized and override the default dom elements return value.
  • It allows you to override or customize default dom element events with your own.

3. useImperativeHandle example with Typescript

import { forwardRef, useImperativeHandle, useRef } from "react"

interface InputProps{
}
type RefHandler = {
}
export const RefForm = () => {
   const nameRef =  useRef() as React.MutableRefObject<HTMLInputElement>;
   const focusHandler = () => {
      nameRef.current.focus()
   }
   const blurHandler = () => {
      nameRef.current.blur()
   }
   const toggleHandler = () => {
      nameRef.current.toggleAttribute("Some Value")
   }
   clearHandler = () => {
      nameRef.current.remove()
   }
   return(
      <>
         <Input ref={nameRef}/>
         <div>
            <button onClick={focusHandler}>Focus</button>
            <button onClick={blurHandler}>Blur</button>
            <button onClick={toggleHandler}>Toggle</button>
            <button onClick={clearHandler}>Clear</button>
         </div>
      </>
   )
}

const Input = forwardRef<RefHandler,InputProps>((props, ref) => {
   const nameRef = useRef() as React.MutableRefObject<HTMLInputElement>;
   useImperativeHandle(ref, () => ({
      focus: () => {
         nameRef?.current?.focus();
      },
      blur: () => {
         alert("Some blur function")
      },
      toggleAttribute: (val: string) => {
         nameRef.current.value = val
      },
      remove: () => {
         nameRef.current.value = ""
      }
   }));
   return(
      <input type="text" name="name" value="" ref={nameRef}/>
   )
})

4. useImperativeHandle example with Javascript

import { forwardRef, useImperativeHandle, useRef } from "react"

export const RefForm = () => {
   const nameRef =  useRef()
   const focusHandler = () => {
      nameRef.current.focus()
   }
   const blurHandler = () => {
      nameRef.current.blur()
   }
   const toggleHandler = () => {
      nameRef.current.toggleAttribute("Some Value")
   }
   const clearHandler = () => {
      nameRef.current.remove()
   }
   const valueHandler = () => {
      alert(nameRef.current.value())
   }
   return(
      <>
         <Input ref={nameRef}/>
            <div>
               <button onClick={focusHandler}>Focus</button>
               <button onClick={blurHandler}>Blur</button>
               <button onClick={toggleHandler}>Toggle</button>
               <button onClick={clearHandler}>Clear</button>
               <button onClick={valueHandler}>Value</button>
            </div>
      </>
   )
}

const Input = forwardRef((props, ref) => {
   const nameRef = useRef()
   useImperativeHandle(ref, () => ({
      focus: () => {
         nameRef?.current?.focus();
      },
      blur: () => {
         alert("Some blur function")
      },
      toggleAttribute: (val) => {
         nameRef.current.value = val
      },
      remove: () => {
         nameRef.current.value = ""
      },
      value: () => {
         return nameRef.current.value + " modified"
      }
   }));
   return(
      <input type="text" name="name" value="" ref={nameRef}/>
   )
})
Lance

By: Lance

Hi, I'm Lance Raney, a dedicated Fullstack Developer based in Oklahoma with over 15 years of exp

Read more...