How to fix Cannot access ref.current in forwardRef before component renders in React

ReactINTERMEDIATEMEDIUMUpdated Dec 9, 2025· 89 views

This error occurs when you try to access ref.current during the render phase of a component using forwardRef, before React has attached the ref to a DOM node. Refs are only populated after the component mounts and the DOM element is created.

Quick fix

Fixes Cannot access ref.current in forwardRef before component renders

import React, { forwardRef, useEffect } from 'react';

const MyInput = forwardRef<HTMLInputElement>((props, ref) => {
  // ❌ WRONG: Accessing ref.current during render
  // console.log(ref.current); // Error!

  useEffect(() => {
    // ✅ CORRECT: Access ref.current after render
    if (ref && typeof ref !== 'function' && ref.current) {
      console.log('Input element:', ref.current);
      ref.current.focus(); // Safe to call DOM methods
    }
  }, [ref]);

  return <input ref={ref} {...props} />;
});
  1. Move ref.current access to useEffect
  2. Add null checks before accessing ref.current
  3. Use useLayoutEffect for synchronous DOM reads
  4. Handle conditional rendering carefully
react — error
import React, { forwardRef, useEffect } from 'react';
const MyInput = forwardRef<HTMLInputElement>((props, ref) => {
// ❌ WRONG: Accessing ref.current during render
// console.log(ref.current); // Error!
useEffect(() => {
// ✅ CORRECT: Access ref.current after render
if (ref && typeof ref !== 'function' && ref.current) {
console.log('Input element:', ref.current);
ref.current.focus(); // Safe to call DOM methods
}
}, [ref]);
return <input ref={ref} {...props} />;
});
Cannot access ref.current in forwardRef before component renders

What this error means

This error happens when you attempt to read or write `ref.current` during the render phase of a React component that uses `forwardRef`. React refs follow a specific lifecycle: they are `null` or `undefined` until after the component has rendered and React has attached the ref to the actual DOM node. When using `forwardRef`, the ref parameter is passed to your component, but it won't have a `.current` value until React completes the render and commit phases. Accessing `ref.current` during rendering breaks React's expectation that components behave like pure functions, making the component's output unpredictable. React cannot track changes to `ref.current` during rendering, which means it won't know when to re-render your component. This is by design - refs are meant for accessing imperative DOM APIs or storing mutable values that don't affect rendering.

Typical symptoms

  • Error thrown when accessing ref.current during component render
  • ref.current is null or undefined even though a ref was passed
  • Component crashes before mounting completes
  • Unexpected behavior when trying to use ref.current in JSX
  • TypeScript errors about ref.current being possibly null

Common causes

  1. Accessing ref.current directly in the component body during render
  2. Reading ref.current in conditional rendering logic
  3. Using ref.current to compute derived state or props during render
  4. Calling methods on ref.current before useEffect or useLayoutEffect runs
  5. Attempting to access ref.current when the element is conditionally rendered and not yet mounted
  6. Not checking if ref.current exists before accessing it

How to fix "Cannot access ref.current in forwardRef before component renders"

1Move ref.current access to useEffect

The most common fix is to move any ref.current access into a useEffect hook, which runs after the component renders and the ref is attached:

tsx
import React, { forwardRef, useEffect } from 'react';

const MyInput = forwardRef<HTMLInputElement>((props, ref) => {
  // ❌ WRONG: Accessing ref.current during render
  // console.log(ref.current); // Error!

  useEffect(() => {
    // ✅ CORRECT: Access ref.current after render
    if (ref && typeof ref !== 'function' && ref.current) {
      console.log('Input element:', ref.current);
      ref.current.focus(); // Safe to call DOM methods
    }
  }, [ref]);

  return <input ref={ref} {...props} />;
});

For immediate DOM manipulation before paint, use useLayoutEffect instead of useEffect.

2Add null checks before accessing ref.current

Always check that the ref exists and has a .current property before accessing it:

tsx
import React, { forwardRef, useEffect } from 'react';

const CustomComponent = forwardRef<HTMLDivElement>((props, ref) => {
  useEffect(() => {
    // Check if ref is an object with current property
    if (ref && typeof ref !== 'function' && ref.current) {
      // Safe to access ref.current here
      const element = ref.current;
      element.style.backgroundColor = 'lightblue';
    }
  }, [ref]);

  return <div ref={ref}>Content</div>;
});

TypeScript users can use optional chaining for cleaner code: ref?.current.

3Use useLayoutEffect for synchronous DOM reads

If you need to read DOM properties (like dimensions) before the browser paints, use useLayoutEffect:

tsx
import React, { forwardRef, useLayoutEffect, useState } from 'react';

const MeasuredComponent = forwardRef<HTMLDivElement>((props, ref) => {
  const [height, setHeight] = useState(0);

  useLayoutEffect(() => {
    if (ref && typeof ref !== 'function' && ref.current) {
      // Measure DOM before browser paints
      const rect = ref.current.getBoundingClientRect();
      setHeight(rect.height);
    }
  }, [ref]);

  return (
    <div ref={ref}>
      Height: {height}px
      {props.children}
    </div>
  );
});

Note: useLayoutEffect blocks browser painting, so use it only when necessary.

4Handle conditional rendering carefully

When the element attached to the ref is conditionally rendered, the ref may remain null even inside effects:

tsx
import React, { forwardRef, useEffect } from 'react';

interface Props {
  show: boolean;
}

const ConditionalInput = forwardRef<HTMLInputElement, Props>(
  ({ show }, ref) => {
    useEffect(() => {
      if (ref && typeof ref !== 'function' && ref.current) {
        ref.current.focus();
      }
      // ref.current will be null if show is false
    }, [ref, show]); // Include show in dependencies

    // Only render input when show is true
    if (!show) return null;

    return <input ref={ref} placeholder="Type here..." />;
  }
);

The ref will only have a .current value when the element is actually rendered.

5Use callback refs for more control

Callback refs give you more control over when and how refs are set:

tsx
import React, { forwardRef, useCallback } from 'react';

const SmartInput = forwardRef<HTMLInputElement>((props, forwardedRef) => {
  const handleRef = useCallback(
    (node: HTMLInputElement | null) => {
      // Called when element mounts
      if (node) {
        console.log('Element mounted:', node);
        node.focus();
      }

      // Forward the ref to parent
      if (typeof forwardedRef === 'function') {
        forwardedRef(node);
      } else if (forwardedRef) {
        forwardedRef.current = node;
      }
    },
    [forwardedRef]
  );

  return <input ref={handleRef} {...props} />;
});

Callback refs are called immediately when the element is attached or detached.

Advanced notes

React 19 Update: In React 19, forwardRef is no longer necessary. You can pass ref as a regular prop:

tsx
// React 19
function MyInput({ ref }) {
  return <input ref={ref} />;
}

Fallback Ref Pattern: If you want a component to have its own internal ref even when no ref is forwarded, use a fallback pattern:

tsx
import React, { forwardRef, useRef } from 'react';

const ComponentWithFallback = forwardRef<HTMLDivElement>((props, forwardedRef) => {
  const fallbackRef = useRef<HTMLDivElement>(null);
  const ref = forwardedRef || fallbackRef;

  // Now ref will always have a value, even if parent doesn't pass one

  return <div ref={ref as React.RefObject<HTMLDivElement>}>Content</div>;
});

useImperativeHandle: When using forwardRef with useImperativeHandle, remember that the imperative methods won't be available until after the component mounts:

tsx
import React, { forwardRef, useImperativeHandle, useRef } from 'react';

interface CustomHandle {
  focus: () => void;
}

const CustomInput = forwardRef<CustomHandle>((props, ref) => {
  const inputRef = useRef<HTMLInputElement>(null);

  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current?.focus();
    },
  }));

  return <input ref={inputRef} />;
});

// Parent usage
function Parent() {
  const ref = useRef<CustomHandle>(null);

  useEffect(() => {
    // Safe to call after mount
    ref.current?.focus();
  }, []);

  return <CustomInput ref={ref} />;
}

Performance Consideration: Accessing refs doesn't trigger re-renders, which is why you can't use ref.current as a dependency in rendering logic. If you need a value that affects rendering, use useState instead.

Frequently asked questions

What does "Cannot access ref.current in forwardRef before component renders" mean?
current during the render phase of a React component that uses forwardRef. React refs follow a specific lifecycle: they are null or undefined until after the component has rendered and React has attached the ref to the actual DOM node. current value until React completes the render and commit phases.
How do I fix "Cannot access ref.current in forwardRef before component renders"?
This error occurs when you try to access ref.current during the render phase of a component using forwardRef, before React has attached the ref to a DOM node. Refs are only populated after the component mounts and the DOM element is created.
What causes "Cannot access ref.current in forwardRef before component renders"?
Accessing ref.current directly in the component body during render Reading ref.current in conditional rendering logic Using ref.current to compute derived state or props during render
Is the "Cannot access ref.current in forwardRef before component renders" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading