If you encounter the TypeScript error, "Cannot assign to 'current' because it is a read-only property
" when using the React useRef
hook, it is likely because the result of useRef
has the type React.RefObject
(which makes the reference object's "current
" property readonly
). It is defined like so:
interface RefObject<T> {
readonly current: T | null;
}
To understand why this is the case, you need to know that RefObject
is returned by one of TypeScript's three overloads for the React useRef()
hook, which are defined as follows:
function useRef<T>(initialValue: T): MutableRefObject<T>;
function useRef<T>(initialValue: T|null): RefObject<T>;
function useRef<T = undefined>(): MutableRefObject<T | undefined>;
Where the MutableRefObject
return type is defined as follows:
interface MutableRefObject<T> { current: T; }
If it's not already clear why and when we get the return type as RefObject
, it is when:
- The initial value of
useRef
is set tonull
(e.g.useRef(null)
), and; - The
current
property is initialized to a specific type (e.g.useRef<HTMLDivElement>
).
For example:
const elem = useRef<HTMLDivElement>(null);
type Test = typeof elem; // Test = React.RefObject<HTMLDivElement>
As you might have already guessed, you can fix this by simply making the result of useRef
directly mutable. This can be done by including | null
in the type of the generic argument. For example:
const elem = useRef<HTMLDivElement|null>(null);
type Test = typeof elem; // Test = React.MutableRefObject<HTMLDivElement|null>
Now, as you can see from the example above, the type of the reference object is a mutable object (i.e. React.MutableRefObject
) which allows modification of the current
property.
This post was published by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.