Mesrai
Back to blog
// essayTechnical Deep Dive

useRef Without .current: A Live Mesrai Trace

Real PR catch: `inputRef.focus()` instead of `inputRef.current?.focus()` — TypeError on mount. Optional-chain fix.

Mesrai TeamAugust 7, 20268 min read

An input component auto-focusing on mount. Author wrote `inputRef.focus()`. TypeScript would have caught it but the file had `any` types. Runtime: TypeError.

The vulnerable diff

tsxcomponents/SearchInput.tsx
// components/SearchInput.tsx
export function SearchInput() {
  const inputRef = useRef<HTMLInputElement>(null);
  useEffect(() => {
    // BUG: inputRef is the ref object, not the DOM node
    inputRef.focus();  // TypeError: inputRef.focus is not a function
  }, []);
  return <input ref={inputRef} />;
}

What is wrong

`useRef<T>(initial)` returns a stable object `{ current: T | null }`. The DOM node is stored in `.current` after React attaches the ref. Methods on the node are reached via `.current.focus()`. Calling `.focus()` on the ref object itself is a no-op because ref objects do not have that method — TypeError at runtime.

The attack

Repro: open the page in dev, look at the console. TypeError on mount.

textexploit
# Browser console:
TypeError: inputRef.focus is not a function
    at SearchInput.useEffect (SearchInput.tsx:7:3)

Component does not mount, surrounding UI may still work depending on error boundary placement.

Mesrai's review comment

textreview-comment.txt
mesraipilot · Bot · reviewed 20 sec ago

[mesrai] [code-review] [Language] [React] [low]

`useRef` returns `{ current: T | null }`, not the value directly.
Access the DOM node via `.current`:

  inputRef.current?.focus();

The optional chaining handles the null case (ref not yet attached
or component unmounted).

If you typed the ref as `useRef<HTMLInputElement>(null)`, TypeScript
should have caught this. Check that `any` hasn't leaked into the
component types.

The fix

tsxcomponents/SearchInput.tsx (fixed)
// components/SearchInput.tsx — fixed
export function SearchInput() {
  const inputRef = useRef<HTMLInputElement>(null);
  useEffect(() => {
    inputRef.current?.focus();
  }, []);
  return <input ref={inputRef} />;
}

`.current?.focus()` reads the node and safely no-ops if null. Standard React-with-DOM pattern.

Why human review missed it

The bug is junior-grade — but it shows up because TypeScript types were widened to `any` somewhere, or the team is still using JS. Mesrai catches the pattern by flagging method calls directly on a `useRef` return value.

Related rules + further reading

Mesrai rule pack: language/react-ref-current — flags method calls on useRef return without .current.

React docs: Manipulating the DOM with Refs.

TypeScript catches if types are strict — but the bug recurs when they're not.

Takeaway

.current is mandatory. The ref is the box; the value is inside. Mesrai catches the missing access.

// try

See it on your next PR.

Free for individuals. Install in two minutes. Mesrai reviews every commit.