Adding Types to Refs in React using TypeScript

avatar

Borislav Hadzhiev

Wed Apr 21 20212 min read

Updated on Wed Apr 21 2021

How to use Typescript to specify the types of refs in react

Adding Types to the useRef React Hook using TypeScript #

Adding types to the useRef hook can be a little confusing initially let's see why that is:

import {useEffect, useRef} from 'react';

export function RefDemo() {
  const inputRef = useRef();

  useEffect(() => {
    inputRef.current.focus();
  }, []);

  return (
    <div>
      <input ref={inputRef} />
    </div>
  );
}

In the above snippet we get a couple of errors - the error when we hover over the ref prop is very verbose and confusing - in summary inputRef.current could be undefined and cannot be assigned to HTMLInputElement.

In order to fix the errors we have to do a couple of things:

  • Add a generic to the useRef hook and pass in HTMLInputElement as the type.

    - const inputRef = useRef();
    + const inputRef = useRef<HTMLInputElement>();
    

    How we got the name is when we hover over the input element we see something like:

    (property) JSX.IntrinsicElements.input: React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>
    

    And we can see the type is HTMLInputElement. We could also control click in VSCode and read the declaration file to get the type of any element.

  • Even after adding the generic, typescript tells us - we might not actually pass the ref onto an input element therefore because we haven't passed an initial value to useRef the value of the ref might be undefined. So we have to tell typescript that the value of inputRef.current is initialized as null and is either null or HTMLInputElement.

    import {useEffect, useRef} from 'react';
    
    export function RefDemo() {
      const inputRef = useRef<HTMLInputElement | null>(null);
    
      useEffect(() => {
        inputRef?.current?.focus();
      }, []);
    
      return (
        <div>
          <input ref={inputRef} />
        </div>
      );
    }
    

Because typescript doesn't know if we're going to assign the ref to the input element we still had to conditionally call the focus() function on the ref.

Further Reading #

Join my newsletter

I'll send you 1 email a week with links to all of the articles I've written that week

Buy Me A Coffee