Forwarding refs to components
Tags: react, javascript, nextjs
Published: 2021-11-18 12:24:57

---
title: Forwarding refs to components
published: true
date: 2021-11-13 00:00:00 UTC
tags: react, javascript, nextjs
canonical_url: https://www.mariokandut.com/how-to-forward-refs-in-react/
---

Refs provide a way to access DOM nodes (or React elements) created in the render method, but why would you forward a reference?

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#forwarding-refs)Forwarding refs

Ref forwarding in React means, that a reference through a component is automatically passed to one of its children. Typically, this is not necessary for most components, but sometimes, it is very useful. Let's find out why.

### [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#forwarding-refs-to-dom-components)Forwarding refs to DOM components

Forwarding refs can be useful in reusable component libraries. Let's consider an `AwesomeButton` component, that renders the native button DOM element.

```
functon AwesomeButton(props) {
  return(
    <button>{props.children}</button>
  )
}
```

React components hide their implementation details, including their rendered output. This means that other components using the `AwesomeButton`, will usually not obtain a ref to the inner DOM element. This **encapsulation** is good, because **it prevents components from relying heavily on each other's DOM structure**. A high level of encapsulation is desirable on application-level, it can be unpractical for highly reusable leaf components (think of the React tree). These leaf components like `AwesomeButton` are used like native DOM elements, like a button, and managing focus, selection or animations require access to their DOM nodes.

Ref-forwarding lets some components take a ref they receive, and pass it further down (forward it) to a child. In the example below the ref passed to `AwesomeButton` is forwarded down to the DOM button, which gives components using the `AwesomeButton` component access to the button DOM node, just like they would use a DOM button directly.

```
const AwesomeButton = React.forwardRef((props, ref) => (
  <button ref={ref}>{props.children}</button>
));

const ref = React.useRef();
<AwesomeButton ref={ref}>Click it</AwesomeButton>;
```

After attaching the `ref`, `ref.current` will point to the `<button>` DOM element.

### [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#forwarding-refs-in-higher-order-components)Forwarding refs in higher-order components

Higher-Order Components or HOCs can benefit from this ref forwarding technique. Let's have a look at a HOC example, which logs component props to the console.

```
function logProps(WrappedComponent) {
  class LogProps extends React.Component {
    componentDidUpdate(prevProps) {
      console.log('old props:', prevProps);
      console.log('new props:', this.props);
    }

    render() {
      return <WrappedComponent {...this.props} />;
    }
  }

  return LogProps;
}
```

The `logProps` HOC passes all props through the wrapped components and, it doesn't affect the rendered output. Let's apply this on the `AwesomeButton`.

```
class AwesomeButton extends React.Component {
  //...
}
export default logProps(AwesomeButton);
```

Then we import the AwesomeButton and apply a reference.

```
import AwesomeButton from './AwesomeButton';
//...
const ref = createRef();
//...
<AwesomeButton
  label="click it"
  handleClick={handleClick}
  ref={ref}
/>;
```

There is one thing to consider, **`ref` is not a prop.** The reference passed to `AwesomeButton`, which is now a Higher-Order-Component, will not be passed down, because ref is not a prop. Instead, the reference will be attached to the HOC `logProps`.

To avoid this we can explicitly forward refs to the inner `AwesomeButton` component using `forwardRef`. The `React.forwardRef` API receives `props` and `ref` parameters and returns a `React.node`.

```
function logProps(Component) {
  class LogProps extends React.Component {
    componentDidUpdate(prevProps) {
      console.log('old props:', prevProps);
      console.log('new props:', this.props);
    }

    render() {
      const { forwardedRef, ...rest } = this.props;

      // Assign the custom prop "forwardedRef" as a ref
      return <Component ref={forwardedRef} {...rest} />;
    }
  }

  // The second parameter in forwardRef can be used as a normal prop.
  return React.forwardRef((props, ref) => {
    return <LogProps {...props} forwardedRef={ref} />;
  });
}
```

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#tldr)TL;DR

- In React `ref` and `key` are handled differently.
- The `React.forwardRef` API receives `props` and `ref` parameters and returns a `React.node`.
- In HOC, it's important to know that `ref` is not a prop and will not be automatically forwarded with other props. `React.forwardRef` has to be used.

Thanks for reading and if you have any **questions** , use the **comment** function or **send me a message** **[@mariokandut](https://www.twitter.com/mariokandut)**. If you want to know more about **[React](https://www.mariokandut.com/tags/react)**, have a look at these [React Tutorials](https://www.mariokandut.com/tags/react).

References (and Big thanks):

[React Docs - Forwarding Refs](https://reactjs.org/docs/forwarding-refs.html),[React Docs - Refs](https://reactjs.org/docs/refs-and-the-dom.html),[Bits and Pieces](https://blog.bitsrc.io/understanding-ref-forwarding-in-react-80accd93ed74),[LogRocket](https://blog.logrocket.com/cleaning-up-the-dom-with-forwardref-in-react/)