Home
React
Advanced Hook: useImperativeHandle()
Daniel Nguyen
Daniel Nguyen
July 16, 2025
1 min

Sometimes, a parent component needs to trigger a specific action inside a child component, such as focusing an input or scrolling a container.

React provides useImperativeHandle to expose a controlled imperative API instead of exposing the underlying DOM element directly.

1. Basic Concept

In React 19, function components can receive ref as a prop without using forwardRef.

import {
useImperativeHandle,
useRef,
type ComponentPropsWithRef,
type Ref,
} from 'react'
type InputAPI = {
focusInput: () => void
}
type MyInputProps = Omit<
ComponentPropsWithRef<'input'>,
'ref'
> & {
ref?: Ref<InputAPI>
}
function MyInput({ ref, ...props }: MyInputProps) {
const inputRef = useRef<HTMLInputElement>(null)
useImperativeHandle(
ref,
() => ({
focusInput() {
inputRef.current?.focus()
},
}),
[],
)
return <input {...props} ref={inputRef} />
}

The parent receives only the focusInput() method, not direct access to the child’s internal input ref.

2. Using the Custom API

function App() {
const myInputRef = useRef<InputAPI>(null)
return (
<>
<MyInput
ref={myInputRef}
placeholder="Enter your name"
/>
<button onClick={() => myInputRef.current?.focusInput()}>
Focus input
</button>
</>
)
}

Clicking the button calls the child component’s exposed method, which focuses the actual input element.

3. Understanding Dependencies

The dependency array determines when React recreates the exposed handle.

useImperativeHandle(
ref,
() => ({
focusInput: () => inputRef.current?.focus(),
}),
[],
)

Why is an empty array appropriate here?

  • inputRef is created by useRef, so its identity is stable.
  • The exposed method reads inputRef.current when called, rather than capturing the current DOM element.
  • The handle does not depend on changing props or state.

If the exposed methods depend on reactive values, include those values in the dependency array to avoid stale closures.

4. When Should You Use It?

Common use cases include:

  • Focusing or selecting an input.
  • Scrolling a child container.
  • Controlling a media element.
  • Exposing a small, intentional API from a reusable component.

Prefer declarative props when possible. For example, use an isOpen prop to control a dialog instead of exposing open() and close() methods unless an imperative interface is genuinely needed.


Tags

#ReactAdvancedHooks

Share

Daniel Nguyen

Daniel Nguyen

Frontend Developer

Frontend developer specializing in React, Next.js, and JavaScript. Writing practical guides on modern web development at Dev98.

Expertise

React
Next.js
JavaScript
TypeScript
Python

Social Media

githublinkedinyoutubewebsite

Related Posts

Advanced Hook
Advanced Hook: useSyncExternalStore()
July 19, 2025
1 min
Dev98

Dev98

React · Next.js · Web development