Carl Rippon

Building SPAs

Carl Rippon
BlogBooks / CoursesAbout
This site uses cookies. Click here to find out more

Forwarding React Refs with TypeScript

November 25, 2020
reacttypescript

In this post, we cover how to forward React refs with TypeScript.

Forwarding React Refs with TypeScript

In the last post, we covered how to use a strongly-typed ref to invoke a method on an HTML element within a React component. What if we want to access an HTML element that isn’t directly in a React component - instead, the HTML element is within a child component.

Let’s imagine we have created a reusable Search component that wraps an input element, like in the example below:

function Search() {
  return <input type="search" />;
}

When consuming Search, let’s imagine we want to set focus to the input element after it has been loaded into the DOM. So, we try to use a ref and set the focus to the input element in a useEffect like below:

function App() {
  const input = React.useRef<HTMLInputElement>(null);

  React.useEffect(() => {
    if (input.current) {
      input.current.focus();
    }
  }, []);

  return <Search ref={input} />;
  // 💥 - Property 'ref' does not exist on type 'IntrinsicAttributes'
}

This doesn’t work though, and a type error is raised when we reference ref on the Search component. 😞

For this to work, we need to forward the ref to the App component. We can acheive this with forwardRef from React:

const Search = React.forwardRef((props, ref) => {
  return <input ref={ref} type="search" />;
});

We wrap the Search component in the forwardRef function, which does the ref forwarding for us.

This raises a type error though, because ref is inferred to be of type unknown. 😞

forwardRef is a generic function that has type parameters for the type of the ref and the props:

const Component = React.forwardRef<RefType, PropsType>((props, ref) => {
  return someComponent;
});

It’s a bit confusing because the ordering of the generic parameters (ref and then props) is the opposite of the ordering of the function parameters (props and then ref). 😕

Anyway, if we add the generic parameter for the ref, the type error is resolved:

const Search = React.forwardRef<HTMLInputElement>((props, ref) => {
  return <input ref={ref} type="search" />;
});

Note that we don’t need to pass the props’ generic parameter because we don’t have any props in this component.

🏃 Play with the code

If you run the CodeSandbox example, we’ll see that focus is set to the input element.

Nice! 😃

Did you find this post useful?

Let me know by sharing it on Twitter.
Click here to share this post on Twitter

If you to learn more about using TypeScript with React, you may find my course useful:

Using TypeScript with React

Find out more