← Back to Chapters

useImperativeHandle() Hook

⚛️ useImperativeHandle()

? Quick Overview

useImperativeHandle() is a React Hook used with forwardRef() to control exactly what a parent component can access from a child component using a ref.

Instead of giving full access to the child’s DOM or instance, you expose only selected methods or values. This improves encapsulation and makes your components safer and cleaner.

? Key Concepts

  • Works only when the child is wrapped with forwardRef()
  • Lets you define a custom API for parent components
  • Reduces direct DOM manipulation from the parent
  • Encourages controlled interaction between components

? Syntax & Theory

? View Code Example
// Expose limited methods or values from a child component
useImperativeHandle(ref, () => ({
  method1() {},
  value: 123
}), [dependencies]);
  • ref → forwarded ref from the parent
  • callback → returns an object containing exposed members
  • dependencies → re-creates the object when values change

? Code Example 1 – Custom Input API

? View Code Example
// Child exposes only focus and clear methods
import React, { useRef, useImperativeHandle, forwardRef } from "react";

const CustomInput = forwardRef((props, ref) => {
  const inputRef = useRef();

  useImperativeHandle(ref, () => ({
    focusInput: () => inputRef.current.focus(),
    clearInput: () => (inputRef.current.value = "")
  }));

  return (
    <input ref={inputRef} type="text" placeholder="Type here..." />
  );
});

function App() {
  const inputRef = useRef();

  return (
    <div>
      <CustomInput ref={inputRef} />
      <button onClick={() => inputRef.current.focusInput()}>Focus</button>
      <button onClick={() => inputRef.current.clearInput()}>Clear</button>
    </div>
  );
}

? Output / Explanation

The parent can only access focusInput() and clearInput(). The actual input element remains hidden, making the component easier to maintain and safer to reuse.

? Code Example 2 – Control UI from Parent

? View Code Example
// Child exposes a color-changing function
import React, { forwardRef, useImperativeHandle, useRef } from "react";

const Box = forwardRef((props, ref) => {
  const divRef = useRef();

  useImperativeHandle(ref, () => ({
    changeColor: color => {
      divRef.current.style.backgroundColor = color;
    }
  }));

  return <div ref={divRef} style={{ width: "150px", height: "100px", background: "blue" }}></div>;
});

function ParentBox() {
  const boxRef = useRef();

  return (
    <div>
      <Box ref={boxRef} />
      <button onClick={() => boxRef.current.changeColor("green")}>Green</button>
      <button onClick={() => boxRef.current.changeColor("orange")}>Orange</button>
    </div>
  );
}

? Output / Explanation

The parent triggers visual changes using only the exposed function — not direct DOM access. This creates a cleaner communication channel between components.

✅ When to Use

  • To restrict ref access to safe methods
  • To control child components like modals or inputs
  • For reusable UI components with custom APIs
  • Avoid using it for normal data flow handling

? Tips & Best Practices

  • Expose only what the parent really needs
  • Prefer props for data flow; use refs only for actions
  • Keep imperative APIs minimal and meaningful
  • Use TypeScript for strong ref typing

? Try It Yourself

  1. Create an input that exposes focus and reset
  2. Build a modal with open and close methods
  3. Log ref values before and after customization
  4. Combine multiple methods inside one imperative handle

Goal: Master controlled component exposure using useImperativeHandle() for clean design and safer APIs.