React refs with TypeScript
In this post, we cover how to use React refs with TypeScript in function and class components.
Creating strongly-typed refs in function components
The useRef
hook can be used to access all the properties and methods of an element.
const element = React.useRef(null);// can access all the properties and methods of `element` via `element.current`...return ( <SomeElement ref={element} />);
It is commonly used when we need to invoke methods on an element imperatively. Below is an example:
function Search() { const input = React.useRef(null); React.useEffect(() => { if (input.current) { input.current.focus(); } }, []); return ( <form> <input ref={input} type="search" /> </form> );};
We are setting focus on an input
when the component first renders.
The type of input.current
is inferred as null
if strict mode is on; otherwise, it is inferred as any
. A type error also occurs when input.current
is referenced if strict mode is on.
Not ideal. π
We can explicitly define the type of the element returned from useRef
by passing a generic type parameter:
const element = React.useRef<ElementType>(null);
So, we can explicitly type the ref in the Search
component as follows:
const input = React.useRef<HTMLInputElement>(null);
The type error now disappears. π
π Play with the code
Creating strongly-typed refs in class components
Letβs implement the Search
component as a class component. Below is a first attempt:
class Search extends React.Component { private input = React.useRef<HTMLInputElement>(null);
componentDidMount() { if (this.input.current) { this.input.current.focus(); } }
render() { return ( <form> <input ref={this.input} type="type" /> </form> ); }}
The useRef
hook canβt be used in class components though. π
In class components, we can get a reference to an element using createRef
. We can use this to revise our implementation of the Search
component:
class Search extends React.Component { private input = React.createRef();
componentDidMount() { if (this.input.current) { this.input.current.focus(); } }
render() { return ( <form> <input ref={this.input} type="type" /> </form> ); }}
The type of the input element is inferred to be unknown
though. This means we get a type error when this.input.current
is referenced. π
We can explicitly define the type of the element returned from createRef
by passing a generic type parameter:
React.createRef<ElementType>();
A revised, more strongly-typed version of the Search
component is below.
class Search extends React.Component { private input = React.createRef<HTMLInputElement>();
componentDidMount() { if (this.input.current) { this.input.current.focus(); } }
render() { return ( <form> <input ref={this.input} type="type" /> </form> ); }}
π Play with the code
If we run the code, we will see that the focus is set on the input after it renders. π
Learn React with TypeScript - 3rd Edition
NewA comprehensive guide to building modern React applications with TypeScript. Learn best practices, advanced patterns, and real-world development techniques.
View on Amazon