Typing useRef
In this page:
Typing DOM Element Refs
Typing a ref meant for a DOM element — useRef<HTMLInputElement>(null) — gives .current the type HTMLInputElement | null, matching that the ref genuinely starts out unattached before the component first renders.
Example: Typing DOM Element Refs
import React, { useRef } from "react";
function TextInput(): React.JSX.Element {
const inputRef = useRef<HTMLInputElement>(null);
return <input ref={inputRef} />;
}
export default TextInput;
Typing Mutable Values
A ref holding a mutable value that isn't a DOM node — like a timer ID — is typed with useRef<number>(initialValue), and unlike state, changing .current never triggers a re-render.
Example: Typing Mutable Values
import React, { useRef } from "react";
function Timer(): React.JSX.Element {
const timerId = useRef<number>(0);
timerId.current = 42;
return <p>Timer id stored: {timerId.current}</p>;
}
export default Timer;
Refs with Nullable Values
Because a DOM ref's .current starts as null, every place you use it needs a null check first, which TypeScript enforces automatically once the ref is typed correctly instead of loosely as any.
Example: Refs with Nullable Values
import React, { useRef, useEffect } from "react";
function Focusable(): React.JSX.Element {
const ref = useRef<HTMLInputElement>(null);
useEffect(() => {
if (ref.current) ref.current.focus();
}, []);
return <input ref={ref} />;
}
export default Focusable;
useRef with useEffect
Combining useRef with useEffect is the standard pattern for reading a DOM node's real dimensions or focusing it after mount, since the ref is guaranteed to be attached by the time the effect runs.
Example: useRef with useEffect
import React, { useRef, useEffect } from "react";
function Measured(): React.JSX.Element {
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
if (ref.current) console.log(ref.current.clientWidth);
}, []);
return <div ref={ref}>content</div>;
}
export default Measured;
Typing Custom Ref Values
Typing a custom ref value forwarded through forwardRef requires specifying the ref's type as the first generic argument, letting a parent component safely call methods exposed by a child through useImperativeHandle.
Example: Typing Custom Ref Values
import React, { forwardRef, useImperativeHandle } from "react";
interface InputHandle {
focus: () => void;
}
const CustomInput = forwardRef<InputHandle>((props, ref) => {
useImperativeHandle(ref, () => ({ focus: () => console.log("focused") }));
return <input />;
});
export default CustomInput;
Chapter Quiz — Complete all 8 topics to unlock
0/8 topics done
Complete these topics first: