Refs
React allows you to grab the instance of an element or component with refs.
Refs with the useRef hook
Inside a component, refs are created with the useRef hook:
1import {useRef} from 'react';2import * as React from 'react';3
4component MyComponent() {5 const buttonRef = useRef<null | HTMLButtonElement>(null);6 return <button ref={buttonRef}>Toggle</button>;7}Note that useRef wraps the ref value in an object with a current property. This must be
reflected in the type of anything accepting the ref value.
The type useRef returns is React.RefObject<T>. Use it to annotate anything that accepts the ref object, such as a helper that reads current:
1import {useRef} from 'react';2import * as React from 'react';3
4function focusInput(ref: React.RefObject<null | HTMLInputElement>) {5 if (ref.current != null) {6 ref.current.focus();7 }8}9
10component MyComponent() {11 const inputRef = useRef<null | HTMLInputElement>(null);12 return <input ref={inputRef} onClick={() => focusInput(inputRef)} />;13}Reading ref.current
The current property starts out null and is only populated after the element mounts, so its type includes null. Refine it with a != null check before using it:
1import {useRef} from 'react';2import * as React from 'react';3
4component MyComponent() {5 const inputRef = useRef<null | HTMLInputElement>(null);6
7 const focusInput = () => {8 inputRef.current.focus(); // ERROR: `current` may be nullincompatible-useCannot call inputRef.current.focus because property focus is missing in null [1].9 if (inputRef.current != null) {10 inputRef.current.focus(); // OK: refined to non-null11 }12 };13
14 return <input ref={inputRef} onClick={focusInput} />;15}Accepting a ref with React.RefSetter
To let a parent attach a ref to your component, add a ref parameter typed with React.RefSetter<T>, where T is the instance you expose. With Component Syntax this is just another parameter:
1import {useRef} from 'react';2import * as React from 'react';3
4component FancyInput(ref: React.RefSetter<HTMLInputElement>) {5 return <input ref={ref} />;6}7
8component Form() {9 const inputRef = useRef<null | HTMLInputElement>(null);10 return <FancyInput ref={inputRef} />;11}You write the ref parameter the same way regardless of the React version you target; behind the scenes Component Syntax compiles it to a React.forwardRef call (React 18) or a plain ref prop (React 19). The ref must be a direct parameter, not nested in a rest parameter. See Ref Parameters for the full explanation.
Callback refs
Instead of a ref object, you can pass a function as a ref. React calls it with the element instance when it mounts, and with null when it unmounts, so the parameter type is T | null:
1import * as React from 'react';2
3component MyComponent() {4 const setButtonRef = (button: HTMLButtonElement | null) => {5 if (button != null) {6 button.focus();7 }8 };9
10 return <button ref={setButtonRef}>Toggle</button>;11}A ref parameter typed React.RefSetter<T> accepts both a ref object and a callback ref, so a component written with the pattern above works with either.
Deriving ref types
To name the type behind a ref without spelling it out, Flow provides two utilities:
React.ElementRef<typeof Component>gives the instance type a component exposes (for exampleHTMLInputElementfor an'input', or a class instance for a class component).React.RefOf<Component>gives the type of thecurrentfield on a component'srefprop, orvoidif it has none.
See Also
- React Types —
React.RefSetter,React.RefObject,React.RefOf,React.ElementRef, and other built-in React types - Ref Parameters — how Component Syntax compiles the ref parameter
- Function and Class Components — typing class components, including their refs