Question presented to candidate:
"You have a custom <Modal> and a parent that needs to open it. Would you reach for useImperativeHandle, and what does forwardRef have to do with it?"
What a strong answer should cover:
- They solve two different problems that used to be paired.
forwardRefpassed a ref through a function component;useImperativeHandledecides what the ref points at. - In React 19,
forwardRefis no longer needed —refis a normal prop on function components. It is still exported for compatibility, but new code does not need the wrapper. useImperativeHandleexists to narrow the surface. A raw DOM ref hands the parent the entire element; an imperative handle exposes only the methods you choose.- That matters because a ref is an escape hatch from one-way data flow, and the smaller the hatch the better — a parent that can reach
innerHTMLwill eventually use it. - It is for imperative actions the DOM genuinely owns: focus, scroll, select text, play/pause media, trigger an animation.
- It is not for state a parent should own. If the parent decides whether a modal is open, that is a prop, not a method.
- The dependency array matters: the handle object is recreated when the deps change, so stale closures apply here too.
Clarifying questions expected:
- "Is this genuinely imperative — focus or scroll — or is it state the parent should own?" — usually the latter, and then neither hook is right.
- "Which React version?" — 19 removes the need for
forwardRef.
Code / implementation expected: Optional. Showing the narrowed handle next to what a bare DOM ref would expose makes the case.