Last updated: Feb 29, 2024
Reading timeยท3 min

Use a type guard to solve the "Object is possibly null" error with the useRef
hook in React, e.g. if (inputRef.current) {}.
Once null is excluded from the ref's type, we can access properties on the
ref that correspond to its type.

Here is an example of how the error occurs.
import {useEffect, useRef} from 'react'; export default function App() { const inputRef = useRef<HTMLInputElement>(null); useEffect(() => { // โ๏ธ Object is possibly 'null'.ts(2531) inputRef.current.focus(); }, []); return ( <div> <input ref={inputRef} type="text" id="message" /> <button>Click</button> </div> ); }
The issue is that TypeScript has no guarantee that we'll assign the ref to an
element or assign a value to it, so its current property could possibly be
null.
To solve the error, use a type guard to exclude null from the ref's type
before accessing properties on it.
import {useEffect, useRef} from 'react'; export default function App() { const inputRef = useRef<HTMLInputElement>(null); useEffect(() => { // ๐๏ธ ref could be null here if (inputRef.current != null) { // ๐๏ธ TypeScript knows that ref is not null here inputRef.current.focus(); } }, []); return ( <div> <input ref={inputRef} type="text" id="message" /> <button>Click</button> </div> ); }

We used a simple if statement as a
type guard
to make sure the current property on the ref does not store a null value.
TypeScript knows that the current property on the ref object does not store
a null value once we enter the if block.
useRef hook to type the current property of your ref correctlyNote that we passed a generic to type the value of the
ref to an HTMLInputElement.
HTML***Element. Once you start typing HTML.., your IDE should be able to help you with autocomplete.Some commonly used types are: HTMLInputElement, HTMLButtonElement,
HTMLAnchorElement, HTMLImageElement , HTMLTextAreaElement,
HTMLDivElement etc.
If you store a different value in your ref, make sure to pass the specific type
to the generic of the useRef() hook, e.g.
const ref = useRef<{name: string}>(null);.
We could have also used the
optional chaining (?.)
operator to short-circuit if the current property on the ref stores a null
value.
import {useEffect, useRef} from 'react'; export default function App() { const inputRef = useRef<HTMLInputElement>(null); useEffect(() => { // ๐๏ธ optional chaining (?.) inputRef.current?.focus(); }, []); return ( <div> <input ref={inputRef} type="text" id="message" /> {/* Cannot find name 'button'.ts(2304) */} <button>Click</button> </div> ); }
The optional chaining (?.) operator short-circuits instead of throwing an error
if the reference is nullish (null or undefined).
current property on the ref stores a null value, the operator would short-circuit returning undefined instead of try to call the focus() method on an undefined value and cause a runtime error.An alternative solution to the error with refs in React is to use the non-null (!) assertion operator.
import {useEffect, useRef} from 'react'; export default function App() { const inputRef = useRef<HTMLInputElement>(null); useEffect(() => { // ๐๏ธ using non-null (!) assertion inputRef.current!.focus(); }, []); return ( <div> <input ref={inputRef} type="text" id="message" /> {/* Cannot find name 'button'.ts(2304) */} <button>Click</button> </div> ); }
null and undefined from a type without doing any explicit type-checking.When we use it, we basically tell TypeScript that the current property on the
ref object does not store a null or an undefined value.
Note that this approach is not type-safe as TypeScript doesn't perform any checks to make sure the property is not nullish.
The "Object is possibly null" error is caused because the useRef() hook can be
passed an initial value as an argument and we're passing it null as an initial
value.
The hook returns a mutable ref object whose .current property is initialized
to the passed argument.
When we pass a ref prop to an element, e.g. <input ref={myRef} />, React sets
the .current property of the ref object to the corresponding DOM node, but
TypeScript can't be sure that we're going to set the ref to a DOM element or set
its value later in our code.