Have you been having issues when trying to use useRef with TypeScript in React or React Native?
Some of the common errors you might see when using useRef with TypeScript include things like “object is possibly ‘null’”, or “MutableRefObject”.
In this post we will cover everything you need in order to know how to use useRef with TypeScript as well as fixing the “object is possibly ‘null’” error as well as any “MutableRefObject” errors you might be having.
It is also worth noting that these fixes not only apply to React, but also apply when using useRef with TypeScript in React Native as well.
useRef is one of the core React hook’s that come shipped directly with React. It lets you use a mutable value that will be persisted across re-renders.
A common use is paring it with components/elements so you can access them and adjust them with vanilla JS. For example if you wanted to get the position of the element.
If you want to learn more about useRef and get a better understanding of it, you should check out this post I have written all about how to use useRef.
Without going into too much detail, what this means is that useRef will enable you to be able to store data inside of a ref that won’t trigger any re-renders and will keep its value between re-renders as well so you won’t ever lose what is inside of it.
One way to think of it is kind of like a state that you can get and set directly without causing re-renders.
With that, let’s dive straight into how you can use it with TypeScript!
How to use useRef with TypeScript.
To use useRef with TypeScript, it is actually pretty easy, all you need to do is provide the type that you want to the function via open and closed chevrons like you would with other React hooks like so: const myRef = useRef<number>(0)
.
Here is an example of how to use useRef with TypeScript:
import React, { useRef } from "react"
export default function ExampleComponent() {
const countRenders = useRef<number>(0)
countRenders.current += 1
return <p>Current renders: {countRenders.current}</p>
}
Firstly, since there are many different uses for refs, we need to look at a few different examples, but they all consist of providing your types via the chevrons to the useRef React hook.
As you can see from the above example, we are allowing the ref to only be of type number.
Now let’s take a look at how this would change if we wanted to use an element.
export default function ExampleComponent() {
const paraRef = useRef<null | HTMLParagraphElement>(null)
return <p ref={paraRef}>Current renders: {countRenders.current}</p>
}
As you can see, instead of providing the number
type, we are now providing the type null | HTMLParagraphElement
which just means the ref can be of types null
or HTMLParagraphElement
.
All we are doing here is providing the correct types to the ref so it can use it as a ref for our paragraph element.
We need to provide a second type of null because the ref won’t start initialized to the paragraph ref because it only gets initialized to that after the first render.
Because of that we need to give it another value to start with temporarily, this can be anything you like but generally it would be null for an element.
The reason why we then need to provide null as the initial argument to useRef
is because otherwise it would be initialized to undefined which won’t match either null
or HTMLParagraphElement
which would cause a type error for MutableRefObject which would be something along the lines of "Type 'undefined' is not assignable to type 'HTMLParagraphElement | null'. ts(2322)"
.
Because we have not added undefined as part of are types we can’t then assign undefined to the ref we have created. To fix this issue we can either ensure we initialize the ref to null, or we could add undefined to the type.
Because we don’t need to use undefined, the best option here is to initialize the useRef hook with null instead.
What is MutableRefObject in TypeScript?
A MutableRefObject is the type of a ref that is returned from useRef in React.
An empty MutableRefObject
will be the type for { current: undefined }
.
This means whatever type you pass in will be used to create the final type that is returned. This is how you would use Generic types which you can read more about here.
For example if you pass in the type string, the type would be returned as MutableRefObject<string>
which will look like { current: string }
If you are seeing an error message including "MutableRefObject"
it probably just means that you haven’t provided the correct type to the useRef hook compared to how you are using your ref.
For example if you have a ref that only accepts null but you are trying to define it as something else then you might see this error:
const exampleRef = useRef<null>(null) // MutableRefObject<null>
exampleRef.current = "test"
// Type '"test"' is not assignable to type 'null'.
However if you then change this to allow strings as well we no longer will get that error:
const exampleRef = useRef<null | string>(null) // MutableRefObject<null | string>
exampleRef.current = "test"
How to fix the “object is possibly ‘null’” error in useRef with TypeScript.
To fix this you just need to make sure you wrap your ref in a condition or use the optional chaining operator to safely check if you can use the ref.
For example this is what your code might look like to get the “object is possibly null” error:
export default function ExampleComponent() {
const paraRef = useRef<null | HTMLParagraphElement>(null)
useEffect(() => {
console.log(paraRef.current.innerHTML) // "object is possibly 'null'"
})
return <p ref={paraRef}>Current renders: {countRenders.current}</p>
}
And to fix it all you need to do is either add a condition or use the optional chaining operator like so:
export default function ExampleComponent() {
const paraRef = useRef<null | HTMLParagraphElement>(null)
useEffect(() => {
console.log(paraRef.current?.innerHTML) // Hello World
})
return <p ref={paraRef}>Hello World</p>
}
To read more about the optional chaining operator and to see how it can benefit you, I highly recommend having a read of my post about nullish coalesing and optional chaining .
For the most part if you have the “object is possibly ‘null’” error message from trying to use useRef in TypeScript, it probably means you are referencing a ref object that could be null because it might not yet have been initialized with an element at the place you are using it.
This means that your ref could equal null
instead of what you want it to equal.
This is because when you first call useRef
it does not start with an element’s ref, and it will only be able to access it after the first render.
This means that before the first render the ref could be null which is where the “object is possibly ‘null’” error comes from.
So by wrapping it in a condition or using the optional chaining operator then you are first checking that the ref exists and that it is not null.
Summary
To summarise how to use useRef with TypeScript in React or React native, the main thing to remember is to make sure that you add in your types using the chevrons, and check to make sure the ref is not null before using it.