Why Does This Happen?
This error occurs when the current
property of the reference is deemed to be immutable. This is the case when:
- A specific type is provided to
useRef()
(e.g.,useRef<number>
), and; - The initial value of
useRef
is set tonull
(e.g.,useRef(null)
).
For instance, this is evident in the following code, where the current
property of the reference object is set as readonly
, triggering a TypeScript error upon reassignment:
// ...
const ref = useRef<number>(null); // immutable
useEffect(() => {
// Error: Cannot assign to current because it is a read-only property.
ref.current = 1;
}, []);
// ...
In this case, internally, the reference "ref
" is assigned the "RefObject
" type, which is defined as:
interface RefObject<T> {
readonly current: T | null;
}
This makes the current
property immutable, as it's marked as readonly
.
How to Fix the Issue?
Depending on your use case, you can resolve this problem by specifying the type for useRef()
in the following ways:
-
Initializing to
null
When initializing the
current
property of the reference object tonull
, you can keep it mutable by appending "| null
" to the generic argument:// ... const ref = useRef<number | null>(null); // mutable useEffect(() => { ref.current = 1; }, []); // ...
Internally, this sets the type as "
MutableRefObject
", which is defined as:interface MutableRefObject<T> { current: T; }
-
Initializing to a Non-Null Value
When you specify the initial value of
useRef()
as a non-null value, it is set as "MutableRefObject
" as well, allowing thecurrent
property of the reference to be mutated:// ... const ref = useRef<number>(2); // mutable useEffect(() => { ref.current = 1; }, []); // ...
-
Initializing to
undefined
When you initialize
useRef()
to anundefined
value, it is set as "MutableRefObject<T | undefined
>" internally, allowing thecurrent
property of the reference to be mutated:// ... const ref = useRef<number>(); // mutable useEffect(() => { ref.current = 1; }, []); // ...
Specifying the type to the React useRef()
hook in any of these ways will allow you to re-assign the current
property of the reference object without TypeScript complaining.
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.