Fix - useRef "Object is possibly null" error in React

avatar

Borislav Hadzhiev

Sat Apr 16 20223 min read

banner

Photo by Aziz Acharki

Fix - useRef "Object is possibly null" error in React #

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 are able to access properties on the ref that correspond to its type.

useref object is possibly null

Here is an example of how the error occurs.

App.tsx
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 in the code snippet is that TypeScript has no guarantee that we'll assign the ref to an element or assign a value to it, so it's current property could possibly be null.

To solve the error, we have to use a type guard to exclude null from the ref's type before accessing properties on it.

App.tsx
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.

Make sure to use the generic on the useRef hook to type the current property of your ref correctly

Note that we passed a generic to type the value of the ref to an HTMLInputElement.

The types of DOM elements are consistently named as 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.

App.tsx
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).

In other words, if the 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 "Object is possibly null" error with refs in React is to use the non-null (!) assertion operator.

App.tsx
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> ); }
The exclamation mark is called the non-null assertion operator in TypeScript. It is used to remove 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.

Use the search field on my Home Page to filter through my more than 1,000 articles.