How to fix useRef: the value returned should be a valid value or reference in React

ReactINTERMEDIATEMEDIUMUpdated Dec 10, 2025ยท 100 views

The "useRef: the value returned should be a valid value or reference" error occurs when React's useRef hook is used incorrectly, typically when trying to access or modify the ref.current property during rendering, passing invalid values to useRef, or using refs in ways that violate React's rendering rules.

Quick fix

Fixes useRef: the value returned should be a valid value or reference

// โŒ WRONG - Accessing ref during render
function MyComponent() {
  const inputRef = useRef(null);
  
  // ๐Ÿšฉ Reading ref during render
  console.log(inputRef.current);
  
  // ๐Ÿšฉ Writing ref during render
  inputRef.current = "some value";
  
  return <input ref={inputRef} />;
}

// โœ… CORRECT - Access ref in event handler
function MyComponent() {
  const inputRef = useRef(null);
  
  function handleClick() {
    // โœ… Reading ref in event handler
    console.log(inputRef.current?.value);
    
    // โœ… Writing ref in event handler
    inputRef.current.focus();
  }
  
  return <input ref={inputRef} onClick={handleClick} />;
}

// โœ… CORRECT - Access ref in effect
function MyComponent() {
  const inputRef = useRef(null);
  
  useEffect(() => {
    // โœ… Safe to access ref in effect
    inputRef.current?.focus();
  }, []);
  
  return <input ref={inputRef} />;
}
  1. Move ref access to event handlers or effects
  2. Use proper initial values for useRef
  3. Use forwardRef for custom components
  4. Use useState for values that trigger re-renders
react โ€” error
// โŒ WRONG - Accessing ref during render
function MyComponent() {
const inputRef = useRef(null);
// ๐Ÿšฉ Reading ref during render
console.log(inputRef.current);
// ๐Ÿšฉ Writing ref during render
inputRef.current = "some value";
return <input ref={inputRef} />;
}
// โœ… CORRECT - Access ref in event handler
function MyComponent() {
const inputRef = useRef(null);
function handleClick() {
// โœ… Reading ref in event handler
console.log(inputRef.current?.value);
// โœ… Writing ref in event handler
inputRef.current.focus();
}
return <input ref={inputRef} onClick={handleClick} />;
}
// โœ… CORRECT - Access ref in effect
function MyComponent() {
const inputRef = useRef(null);
useEffect(() => {
// โœ… Safe to access ref in effect
inputRef.current?.focus();
}, []);
return <input ref={inputRef} />;
}
useRef: the value returned should be a valid value or reference

What this error means

This error message indicates that React's useRef hook is being used in a way that violates its intended purpose or React's rendering rules. The useRef hook creates a mutable reference object with a current property that persists across component renders without triggering re-renders. This error typically surfaces when developers attempt to read or write to ref.current during the rendering phase, pass invalid initial values to useRef, or use refs in contexts where they shouldn't be used. React enforces strict rules about when refs can be accessed because refs are designed to store mutable values that don't affect the visual output. Reading or writing refs during rendering can lead to unpredictable behavior since React may call component functions multiple times (especially in Strict Mode during development). The error serves as a guardrail to prevent common anti-patterns that could break React's rendering consistency or cause subtle bugs in your application.

Typical symptoms

  • Error message states "useRef: the value returned should be a valid value or reference"
  • Component crashes or behaves unpredictably when ref.current is accessed during rendering
  • Ref values appear to be null or undefined when accessed in event handlers or effects
  • Component works in some scenarios but fails in others, especially with conditional rendering
  • Error occurs when trying to pass a ref to a custom component without proper forwarding
  • Application behaves differently in development (Strict Mode) vs production builds
  • Ref.current returns unexpected values or seems to reset between renders

Common causes

  1. Reading or writing ref.current during the rendering phase instead of in event handlers or effects
  2. Passing an invalid initial value to useRef (like a function that returns a value instead of the value itself)
  3. Trying to use ref.current in JSX expressions or during component return
  4. Accessing ref.current in conditional statements or loops during rendering
  5. Using refs to store values that should trigger re-renders (useState should be used instead)
  6. Passing a ref to a custom component without using forwardRef
  7. Creating expensive objects in useRef initialization that get recreated on every render
  8. Mutating ref.current in ways that could affect React's ability to track component state

How to fix "useRef: the value returned should be a valid value or reference"

1Move ref access to event handlers or effects

Ensure you only read or write ref.current in event handlers, useEffect, or useLayoutEffect, not during rendering:

jsx
// โŒ WRONG - Accessing ref during render
function MyComponent() {
  const inputRef = useRef(null);
  
  // ๐Ÿšฉ Reading ref during render
  console.log(inputRef.current);
  
  // ๐Ÿšฉ Writing ref during render
  inputRef.current = "some value";
  
  return <input ref={inputRef} />;
}

// โœ… CORRECT - Access ref in event handler
function MyComponent() {
  const inputRef = useRef(null);
  
  function handleClick() {
    // โœ… Reading ref in event handler
    console.log(inputRef.current?.value);
    
    // โœ… Writing ref in event handler
    inputRef.current.focus();
  }
  
  return <input ref={inputRef} onClick={handleClick} />;
}

// โœ… CORRECT - Access ref in effect
function MyComponent() {
  const inputRef = useRef(null);
  
  useEffect(() => {
    // โœ… Safe to access ref in effect
    inputRef.current?.focus();
  }, []);
  
  return <input ref={inputRef} />;
}

Refs are for side effects and should not affect what gets rendered.

2Use proper initial values for useRef

Pass the actual value you want as the initial ref.current, not a function or expression that needs evaluation:

jsx
// โŒ WRONG - Passing a function instead of value
function MyComponent() {
  // ๐Ÿšฉ Function will be called, but ref.current becomes the function
  const ref = useRef(() => new ExpensiveObject());
  
  // Now ref.current is a function, not an ExpensiveObject
  ref.current(); // This calls the function
}

// โœ… CORRECT - Pass the value directly
function MyComponent() {
  const ref = useRef(new ExpensiveObject());
  
  // ref.current is now an ExpensiveObject
  ref.current.doSomething();
}

// โœ… BETTER - Lazy initialization for expensive objects
function MyComponent() {
  const ref = useRef(null);
  
  if (ref.current === null) {
    ref.current = new ExpensiveObject(); // Only created once
  }
  
  return <div>{/* ... */}</div>;
}

For expensive objects, use lazy initialization to avoid recreating on every render.

3Use forwardRef for custom components

When passing a ref to a custom component, you must use forwardRef to expose the underlying DOM element:

jsx
// โŒ WRONG - Custom component doesn't forward ref
function MyInput(props) {
  return <input {...props} />;
}

function Parent() {
  const inputRef = useRef(null);
  
  // ๐Ÿšฉ Ref won't work - MyInput doesn't forward it
  return <MyInput ref={inputRef} />;
}

// โœ… CORRECT - Using forwardRef
const MyInput = forwardRef(function MyInput(props, ref) {
  return <input {...props} ref={ref} />;
});

function Parent() {
  const inputRef = useRef(null);
  
  // โœ… Ref works - forwarded to actual input
  return <MyInput ref={inputRef} />;
}

forwardRef passes the ref through to the underlying DOM element or component.

4Use useState for values that trigger re-renders

If changing a value should cause the component to re-render, use useState instead of useRef:

jsx
// โŒ WRONG - Using ref for state that should trigger re-render
function Counter() {
  const countRef = useRef(0);
  
  function increment() {
    countRef.current += 1;
    // ๐Ÿšฉ Component won't re-render!
  }
  
  return (
    <div>
      <button onClick={increment}>Increment</button>
      <div>Count: {countRef.current}</div> {/* ๐Ÿšฉ Won't update! */}
    </div>
  );
}

// โœ… CORRECT - Using state for reactive values
function Counter() {
  const [count, setCount] = useState(0);
  
  function increment() {
    setCount(count + 1); // โœ… Triggers re-render
  }
  
  return (
    <div>
      <button onClick={increment}>Increment</button>
      <div>Count: {count}</div> {/* โœ… Updates automatically */}
    </div>
  );
}

Use refs for values that persist but don't affect rendering; use state for reactive values.

5Avoid ref access in conditional rendering

Don't access ref.current in conditions or expressions that affect what gets rendered:

jsx
// โŒ WRONG - Ref access affects rendering
function MyComponent({ showInput }) {
  const inputRef = useRef(null);
  
  return (
    <div>
      {showInput && (
        <input ref={inputRef} />
      )}
      
      {/* ๐Ÿšฉ Reading ref in render expression */}
      <div>Value: {inputRef.current?.value || "empty"}</div>
    </div>
  );
}

// โœ… CORRECT - Store ref value in state if needed for rendering
function MyComponent({ showInput }) {
  const inputRef = useRef(null);
  const [inputValue, setInputValue] = useState("");
  
  function handleChange(e) {
    setInputValue(e.target.value);
  }
  
  return (
    <div>
      {showInput && (
        <input ref={inputRef} onChange={handleChange} />
      )}
      
      {/* โœ… Using state instead of ref for rendering */}
      <div>Value: {inputValue || "empty"}</div>
    </div>
  );
}

If you need a value for rendering, it should be in state, not a ref.

6Check for Strict Mode double rendering

In development with React Strict Mode, components render twice. Ensure your ref logic handles this:

jsx
function MyComponent() {
  const renderCountRef = useRef(0);
  
  // This will increment twice in Strict Mode dev
  renderCountRef.current += 1;
  
  console.log(`Render count: ${renderCountRef.current}`);
  // In Strict Mode: logs 1, then 2
  
  // โœ… Better: Use effect for side effects
  useEffect(() => {
    // This runs once after mount in dev too
    console.log("Effect ran");
  }, []);
  
  return <div>Component</div>;
}

// Enable Strict Mode in your app:
// index.js or main.jsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <App />
  </StrictMode>
);

Strict Mode helps catch side effects during rendering but can cause ref values to update unexpectedly.

Advanced notes

The useRef hook is often misunderstood as a way to "escape" React's rendering model, but it's actually tightly integrated with React's lifecycle. When you call useRef, React creates a ref object that's associated with the specific component instance. This ref object persists across re-renders because React maintains a reference to it in its internal fiber tree.

One subtle aspect is that refs are not truly "outside" of React's control - they're part of the component instance. This is why accessing them during rendering causes issues: React needs to complete the render phase before side effects (including ref mutations) can be safely applied.

For complex scenarios where you need to coordinate refs across multiple components or manage refs in libraries, consider using the useImperativeHandle hook to expose specific methods from child components, or create custom hooks that manage ref logic internally. Remember that refs are primarily for imperative DOM operations and storing mutable values that don't affect the visual output.

Frequently asked questions

What does "useRef: the value returned should be a valid value or reference" mean?
This error message indicates that React's useRef hook is being used in a way that violates its intended purpose or React's rendering rules. The useRef hook creates a mutable reference object with a current property that persists across component renders without triggering re-renders. current during the rendering phase, pass invalid initial values to useRef, or use refs in contexts where they shouldn't be used.
How do I fix "useRef: the value returned should be a valid value or reference"?
The "useRef: the value returned should be a valid value or reference" error occurs when React's useRef hook is used incorrectly, typically when trying to access or modify the ref.current property during rendering, passing invalid values to useRef, or using refs in ways that violate React's rendering rules.
What causes "useRef: the value returned should be a valid value or reference"?
Reading or writing ref.current during the rendering phase instead of in event handlers or effects Passing an invalid initial value to useRef (like a function that returns a value instead of the value itself) Trying to use ref.current in JSX expressions or during component return
Is the "useRef: the value returned should be a valid value or reference" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading