When to Avoid Forwarding Refs in React
React’s forwardRef API is a powerful tool that allows
components to take a ref they receive and pass it further
down to a child component. While useful for accessing DOM nodes in
reusable leaf components like buttons or inputs, forwarding refs is
often overused. This article explains when you should avoid using
forwardRef in React and outlines better alternative
patterns to maintain clean, declarative, and maintainable codebases.
1. When It Breaks Component Encapsulation
Encapsulation is a core principle of component-based architecture. When you forward a ref to a child component’s internal DOM node, you expose that component’s internal structure to its parent.
If the parent component relies on the specific DOM structure of the
child (such as expecting a <div> instead of a
<span>), any future refactoring of the child
component can silently break the parent. Avoid forwarding refs when you
want to keep the internal implementation details of a component
private.
2. When Props and State Can Achieve the Same Goal
React is designed around a declarative, unidirectional data flow. Developers often reach for refs to imperatively trigger actions—such as playing a video, opening a modal, or resetting a form—when these can be easily managed using declarative props and state.
- Avoid: Forwarding a ref to call
ref.current.openModal()from a parent component. - Better Approach: Pass an
isOpenboolean prop to the child component and let the child react to changes in that prop.
3. When Creating Simple Wrapper Components
If you are writing a high-level wrapper component (such as a Layout, Card, or Sidebar) that merely groups other elements, forwarding refs is usually unnecessary.
Unless the parent component specifically needs to measure the layout
dimensions or track the scroll position of that wrapper, adding
forwardRef introduces unnecessary boilerplate and
complexity. Keep your components simple until a concrete requirement for
DOM access arises.
4. When
Exposing Custom Methods via useImperativeHandle
While React allows you to pair forwardRef with
useImperativeHandle to customize the ref instance value
exposed to parent components, this should be a last resort.
Abusing this pattern turns React components into imperative objects reminiscent of jQuery or class-based programming. If you find yourself exposing multiple custom methods through a ref to control a child component, it is a strong signal that your application state should be lifted up to the parent component instead.
5. When a Callback Prop is Cleaner
Sometimes a parent component only needs access to a DOM node at the moment it mounts (for example, to initialize a third-party non-React library). Instead of forwarding a ref all the way down, you can pass a simple callback function as a prop.
// Instead of forwarding a ref, use a callback prop
function ChildComponent({ onElementMount }) {
return <div ref={onElementMount} />;
}This approach avoids the complexity of React.forwardRef
and keeps the data flow explicit and easy to trace.