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. π
Did you find this post useful?
Let me know by sharing it on Twitter.If you to learn more about using TypeScript with React, you may find my course useful: