Manipulate DOM Elements in External React Components with ForwardRef
Tags: react, webdev, programming, javascript
Published: 2021-01-20 23:06:19

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

React is a library for creating front end views. It has a large ecosystem of libraries that work with it. Also, we can use it to enhance existing apps.

To manipulate DOM elements directly with React, we can create a `ref`, associate it to an element, and then reference that and call its methods to manipulate the DOM item directly.

In this article, we’ll look at how to pass the ref to components outside of its originating component by forwarding refs.

Forwarding refs to DOM components
=================================

We can forward refs by creating a ref and then call the `forwardRef` method to get the ref and then pass it into any place we want.

For example, if we have a `Button` component that returns a `button` element, and we want to get the `button` element from the outside component, we can write the following:

```
const Button = React.forwardRef((props, ref) => (  
  <button id="custom-button" ref={ref}>  
    {props.children}  
  </button>  
));

class App extends React.Component {  
  constructor(props) {  
    super(props);  
    this.state = {};  
    this.buttonRef = React.createRef();  
  } componentDidMount() {  
    this.buttonRef.current.focus();  
  } render() {  
    return <Button ref={this.buttonRef}>Click Me</Button>;  
  }  
}
```

In the code above, we have a `Button` component created by using the `React.forwardRef` method with a callback passed in.

The callback has a `props` parameter which has the props that are passed in from the parent component, and the `ref` object which has the ref that’s passed in from the parent component.

Then we set the `ref` prop of the `button` element to the `ref` from the parameter.

Then we can create a new ref in the `App` component by calling `React.createRef` in `App` ‘s constructor. Then we pass that into the `ref` prop of `Button` so that we can access the ForwardRef from the `button` element.

This means the `this.buttonRef` is referencing the `button` element because we passed it into `Button` , which passes `this.buttonRef` into the `button` element via the callback we passed into `React.forwardRef` .

Then in the `App` component, we call:

```
this.buttonRef.current.focus();
```

in `componentDidMount` to focus the `button` in `Button` from `App` .

Forwarding refs in Higher-Order Components
==========================================

We can also forward refs in high-order components. To do this, we write something like the following:

```
const Button = ({ forwardedRef, children }) => (  
  <button ref={forwardedRef}>{children}</button>  
);

function logProps(Component) {  
  class LogProps extends React.Component {  
    componentDidMount() {  
      console.log(this.props);  
    } 

    render() {  
      const { forwardedRef, ...rest } = this.props;  
      return <Component forwardedRef={forwardedRef} {...rest} />;  
    }  
  } 

  return React.forwardRef((props, ref) => {  
    return <LogProps {...props} forwardedRef={ref} />;  
  });  
}

class App extends React.Component {  
  constructor(props) {  
    super(props);  
    this.buttonRef = React.createRef();  
  } 

  componentDidMount() {  
    this.buttonRef.current.focus();  
  } 

  render() {  
    const ButtonLogProp = logProps(Button);  
    return <ButtonLogProp ref={this.buttonRef}>Click Me</ButtonLogProp>;  
  }  
}
```

In the code above, we have the `logProps` higher-order component. The `logProps` component takes a `Component` .

`logProps` return a component with the forwarded refs passed in by calling `React.forwardRef` with a callback that returns `LogProps` .

In the `App` component we pass `this.buttonRef` as the value to `ButtonLogProp` .

`ButtonLogProp` is created by calling `logProps` with the `Button` component passed in. This means `Component` is `Button` in `logProp` .

`Component`, which is `Button` is then returned in the `render` method of the `LogProp` component.

At the end of the `logProp` higher-order component, we return the component with returned from `React.forwardRef` . The callback we pass into `forwardRef` returns the `LogProps` component with the props including the forwarded ref passed in.

All the props will then reach the `Button` component, which sets the `ref` of the `button` element to the `this.buttonRef` , which is first passed into `logProp` , then passed into `LogProp` , and `React.forwardRef` returns a component with the forwarded ref passed to the `Button` component, and then into the `button` element.

In other words, we passed the ref from `App` , to `logProp` , to `LogProp` , then forwarded with `React.forwardRef` to `Button` and then to `button` .

Conclusion
==========

We can use refs from external components by forwarding refs. This lets us manipulate DOM elements from external components within a component.

Forwarding refs also works with higher-order components. All we have to do is to return the component we want to return in the higher-order component in the `React.forwardRef` callback with the forwarded ref passed in.