Sometimes you need to step outside and interact with components imperatively, for example:
This is where imperative handles come in.
React provides useImperativeHandle to expose imperative APIs safely.
In React 19, you can access ref directly from props — no more forwardRef.
type InputAPI = { focusInput: () => void }function MyInput({ref,...props}: React.InputHTMLAttributes<HTMLInputElement> & {ref: React.RefObject<InputAPI>}) {const inputRef = useRef<HTMLInputElement>(null)useImperativeHandle(ref,() => ({focusInput: () => inputRef.current?.focus(),}),[])return <input ref={inputRef} {...props} />}
function App() {const myInputRef = useRef<InputAPI>(null)return (<div><MyInput ref={myInputRef} placeholder="Enter your name" /><button onClick={() => myInputRef.current?.focusInput()}>Focus input</button></div>)}
Even though we’re using inputRef inside the callback, we don’t need to add it to the dependency array.
Why?
useImperativeHandle lets child components expose custom APIs to parentsref via props (no forwardRef)