All about React's createRef method
Tags: react, javascript, beginners, webdev
Published: 2021-02-01 19:14:24


_by [Felix Gerschau](https://dev.to/fgerschau)_

React refs are a useful and powerful tool that we can use to get even more control over the elements in our application.

In this article, you'll learn what you need to know about refs and how to use them in your class and function components.

> Do you want to see a working example? [Click here](#full-example) to skip the explanation.
>
> Or have a look at the [codepen here](https://codepen.io/fgerschau/pen/mdrgXqL).

## What are refs in React?

"Ref" is short for reference, and it's a React feature that allows us to store a component or DOM element of our application in a variable and access it programmatically.

We can use refs to access DOM elements and React components.

## When (not) to use refs

The [official React documentation](https://reactjs.org/docs/refs-and-the-dom.html) states that the following use cases are a good fit for using refs:

* Managing focus, text selection, or media playback.
* Triggering imperative animations.
* Integrating with third-party DOM libraries.

They also say that we should avoid using refs for anything that can be done **declaratively**.

Declaratively in React means we should **use the JSX syntax** whenever we can, **instead of using JavaScript** to update our application.

Leaving the DOM updates to React makes sense. After all, React is designed to update the elements on our websites as efficiently as possible.

Sometimes though, React doesn't provide the functionality we need, in which case we need to fall back to plain JavaScript.

If we were to get a DOM element in Vanilla JavaScript, we'd use functions like `document.getElementById` or `document.getElementsByClassName`.

```jsx
const inputElement = document.getElementById('input-element-id');
inputElement.focus();
```

But React offers a more convenient way to access elements in our application: Refs.

Every class component and HTML element in React accepts the `ref` prop, which we can use to store a reference to this element.


## How to use createRef

That was enough of theory for now. Let's have a look at how we can use refs in our applications.

For this tutorial, I created a small [codepen](https://codepen.io/fgerschau/pen/mdrgXqL) that allows you to enter your name and **focus the input** when you click on the button.

![React createRef example](https://asayer-content.s3.eu-central-1.amazonaws.com/6e6f3fbdb40542f8bdec6378b9614b02.png)

The HTML input element doesn't accept any `focus` prop that we could use to focus it. However, the HTML node *does* expose the `focus` function.

We somehow need to get access to the element in our code so we can call this function. Instead using `getElementById`, we'll use React's refs.

First, we need to create a new variable in our class where we will store the reference. Mine has the creative name `inputRef`.

```jsx{3}
constructor(props) {
  super(props);
  this.inputRef = React.createRef();
  // ...
}
```

We initialize the variable with `createRef`, which allows us to simply pass the variable to the element that we want to reference.

```jsx{2}
<input
  ref={this.inputRef}
  value={this.state.name}
  onChange={this.handleInputChange}
/>
```

That's everything we need to do to get access to the input element.

The `inputRef` variable now contains a reference to the `input` element.

If we were to inspect the variable at this point, it would look something like this.

```terminal
▶ Object
  ▶ current: input
  ▶ __proto__: Object
```

We can focus the input element by calling the focus function in the `onClick` handler function.

```jsx{1}
<button
  onClick={() => this.inputRef.current?.focus()}
>
  Focus
</button>
```

In case you are wondering, adding the question mark is called the optional chaining, first introduced by TypeScript. It allows us to safely access `current` without worrying about it being undefined or null.

### Full example

Putting everything together, the code of that component looks like the following:

```jsx{4,23,28}
class App extends React.Component {
  constructor(props) {
    super(props);
    this.inputRef = React.createRef();
    this.state = {
      name: '',
    };
  }

  handleInputChange = (e) => {
    e.preventDefault();
    this.setState({ name: e.target.value });
  }

  render() {
    return (
      <>
        <h1>Hi {this.state.name || 'there'}! ??</h1>
        <p>
          What's your name?
        </p>
        <input
          ref={this.inputRef}
          value={this.state.name}
          onChange={this.handleInputChange}
        />
        <button
          onClick={() => this.inputRef?.current?.focus()}
        >
          Focus
        </button>
      </>
    );
  }
}
```


This code is also available on [codepen](https://codepen.io/fgerschau/pen/mdrgXqL).

### Referencing class components

With refs, we can also reference other React components. When we do this, instead of receiving a DOM node, `current` will contain the **mounted instance** of that component.

Note that this **doesn't work with function components** because, unlike class components, they don't have instances.

When dealing with class components, the syntax is the same as with DOM elements:

```jsx
<MyComponent ref={this.myComponentRef} />
```

You don't need to change anything in `MyComponent`.


### Referencing function components using forwardRef

I know that just one moment ago I said that you can't reference function components. However, if you really need to do this, you can **forward** the ref to a DOM element.

For that, we use the `forwardRef` function.

```jsx
const MyInputComponent = React.forwardRef((props, ref) => (
  <input ref={ref} />
));
```

This doesn't allow us to reference the functional component itself but one of the native elements that it renders.

With this modification, we can use the `ref` prop as we did with class components and HTML elements.

```jsx
const MyInputComponent = React.forwardRef((props, ref) => {
  return (
    <input
      ref={ref}
      value={props.name}
      onChange={props.onChange}
    />
  );
});
```

In `App` we can pass down the `ref` property like before.

```jsx
class App extends React.Component {
  //...

  render() {
    return (
      <>
        <MyInputComponent
          ref={this.inputRef}
          name={this.state.name}
          onChange={this.handleChange}
        />

      </>
    );
  }
}
```

I created a seperate [codepen](https://codepen.io/fgerschau/pen/MWjMeLp) for this example.

### Other ways to reference elements

Above I only explained one way of creating refs because I believe it's the easiest way of doing so.

You can do this differently though, and you might encounter these ways of creating refs in some code bases.

#### Callback refs

The `ref` prop, besides accepting objects created with `createRef`, also accepts a *callback*.

```jsx{2}
<input
  ref={(e) => this.inputRef = e}
  value={this.state.name}
  onChange={this.handleInputChange}
/>
```

Note that we don't access the `current` field in the callback because **the function directly receives the element**.

Because of this, we don't need to initialze the variable with `createRef`. We can set it to `null` in the constructor:

```jsx{3}
constructor(props) {
  super(props);
  this.inputRef = null;
  this.state = {
    name: '',
  };
}
```

When accessing the element in our code, we can again omit `current` as `inputRef` already contains the element:

```jsx{2}
<button
  onClick={() => this.inputRef?.focus()}
>
  Focus
</button>
```

The callback will be called with the element once the component mounts, and it will be called with `null` before the component unmounts.

React guarantees that it will be up to date before `componentDidMount` or `componentDidUpdate` are executed.

## How to use useRef

The `createRef` function we know from class components also has its counterpart for functional components: The `useRef` hook.

We first need to initialize the variable.

```jsx
const inputRef = useRef(null);
```

We then pass this value to the `ref` prop:

```jsx
<input
  ref={inputRef}
  value={name}
  onChange={handleChange}
/>
```

The usage of this hook is **very similar to createRef**. However, there are some other use-cases that I discuss in [my article about React's useRef hook](https://felixgerschau.com/useref-react-hooks/).


## Observability for Production React Apps
While you're testing the createRef method, and how to interact directly with DOM references, debugging your React apps in production may be challenging and time consuming. Asayer is a frontend monitoring tool that replays everything your users do and shows how your app behaves and renders for every issue. It’s like having your browser’s inspector open while looking over your user’s shoulder.
![Asayer Frontend Monitoring](https://asayer-content.s3.eu-central-1.amazonaws.com/eb8f28fc4852447eb750d1747c53e692.png)
Asayer helps to quickly get to the root cause by reproducing issues as if they happened in your own browser. It also monitors your frontend performance by capturing key metrics such as page load time, memory consumption and slow network requests as well as *Redux* actions/state.
Happy debugging, for modern frontend teams - [Start monitoring your web app for free](https://asayer.io/register.html).



## Conclusion

React's refs are a useful tool for situations where we can't do things the "*React way*".

I hope that with this article, you have a good overview of how and when to use them.