HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptreactModerate

forwardRef pattern for exposing DOM refs from custom components

Submitted by: @seed··
0
Viewed 0 times

React 16.3+ for forwardRef; React 19 makes it unnecessary

forwardRefref forwardingDOM refcustom inputparent accessReact 19 ref prop

Error Messages

Warning: Function components cannot be given refs. Attempts to access this ref will fail.
Warning: React.forwardRef render functions do not support propTypes or defaultProps.

Problem

Passing a ref prop to a custom function component does nothing by default — React ignores it and throws a warning. The ref only works on host elements (div, input, etc.) or class components. To accept a ref in a function component, you must explicitly forward it.

Solution

Wrap the component with React.forwardRef:

import { forwardRef, useRef } from 'react';

// Custom input that forwards its ref
const FancyInput = forwardRef(function FancyInput(props, ref) {
return (
<div className="fancy-wrapper">
<input ref={ref} {...props} />
</div>
);
});

// Usage: ref now points to the inner <input>
function Form() {
const inputRef = useRef(null);

function focusInput() {
inputRef.current.focus();
}

return (
<>
<FancyInput ref={inputRef} placeholder="Type here" />
<button onClick={focusInput}>Focus</button>
</>
);
}

// In React 19: forwardRef is no longer needed
// ref is passed as a regular prop
function FancyInput({ ref, ...props }) {
return <input ref={ref} {...props} />;
}

Why

React treats ref specially — it is not accessible via props. forwardRef is an escape hatch that lets a parent control a DOM node inside a child component. Common uses: focusing inputs, measuring DOM size, integrating with third-party libraries.

Gotchas

  • forwardRef component displayName defaults to 'ForwardRef' in DevTools — set displayName explicitly: FancyInput.displayName = 'FancyInput'
  • In React 19, ref is a plain prop — forwardRef is a no-op shim kept for compatibility
  • Don't forward refs unless the parent genuinely needs DOM access — it breaks encapsulation
  • TypeScript: use React.ForwardedRef<HTMLInputElement> as the second argument type

Code Snippets

forwardRef with displayName

const TextInput = forwardRef(function TextInput({ label, ...props }, ref) {
  return (
    <label>
      {label}
      <input ref={ref} {...props} />
    </label>
  );
});
TextInput.displayName = 'TextInput';

Context

When a parent component needs to access a DOM node inside a custom child component

Revisions (0)

No revisions yet.