When to use React's Ref on a DOM node in React

In the past there has been a lot of confusion around the ref attribute in React. The attribute makes it possible to reference a DOM node in order to access it and to interact with it. This article should give some clarification around the ref attribute in React. It shows you how you can use it, when you should use it and where it can be used.

On a side note: Don’t mistake the ref attribute with the this.refs object. The latter was used in React in the past. There you would have used a string over a callback function to reference a DOM node. It was deprecated in favor of the ref attribute.

How does React's Ref attribute work?

An input element is the perfect example to showcase the ref attribute. When you learn React, you often wonder how you can get the value in an input element. The following example shows how you can access it:

class SearchForm extends Component {

    constructor(props) {
        super(props);

        this.onSubmit = this.onSubmit.bind(this);
    }

    onSubmit(event) {
        const value = this.input.value;

        // do something with the search value
        // e.g. propagate it up to the parent component
        // (not relevant to show the use case of the ref attribute)
        this.props.onSearch(value);

        event.preventDefault();
    }

    render() {
        return (
            <form onSubmit={this.onSubmit}>
                <input
                    ref={node => this.input = node}
                    type="text"
                />
                <button type="submit">
                    Search
                </button>
            </form>
        );
    }
}

The input element defines a ref attribute. The ref attribute definition always follows the same pattern: ref={node => this.input = node}. When the component renders the first time, you want to bind the DOM node to the this object of the component. Then you have access to the DOM node. In the code snippet above it is used to get the input value of the input element when you submit the form.

When to use React's Ref attribute?

But it is not always a good idea to use the ref attribute. The general rule of thumb is to avoid it. The official React documentation mentions three occasions where you can use it because you have no other choice.

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

First, you can use the ref attribute to access the DOM API (What’s an API?). You can get a value of an input element yet you can also trigger methods like a focus(). It gives you control over the DOM API, for instance to use the media elements.

Second, you can use it to integrate with third-party libraries that rely on the DOM. D3.js is such an use case, because it has to hook into the DOM and it has its own DOM manipulation API. For instance, you might want to integrate a D3 component in your React component hierarchy. Therefore you can use a ref attribute as an entry point for the D3 component. You leave the React world and access the D3 world.

Last but not least, you can trigger animations imperatively on your elements.

These are the only occasions where you should use the ref attribute in your React DOM.

Let’s revisit the input element and the value retrieval. It could be solved differently, couldn’t it? By using the state in React to store the input value instead of using the element instance, you can cut down the ref attribute.

class SearchForm extends Component {

    constructor(props) {
        super(props);

        this.state = { value: '' };

        this.onSubmit = this.onSubmit.bind(this);
    }

    onSubmit(event) {
        const value = this.state.value;

        this.props.onSearch(value);

        event.preventDefault();
    }

    render() {
        return (
            <form onSubmit={this.onSubmit}>
                <input
                    onChange={event => this.setState({ value: event.target.value })}
                    type="text"
                />
                <button type="submit">
                    Search
                </button>
            </form>
        );
    }
}

Now you would use the internal component state instead of the ref attribute. In addition, you have a single source of truth for the input value in your component state and can use it to close the loop of the unidirectional data flow in React.

class SearchForm extends Component {

    ...

    render() {
        return (
            <form onSubmit={this.onSubmit}>
                <input
                    onChange={event => this.setState({ value: event.target.value })}
                    type="text"
                    value={this.state.value}
                />
                <button type="submit">
                    Search
                </button>
            </form>
        );
    }
}

Especially in forms, with multiple input elements, it can make sense to exchange the ref attribute with the state solution. It follows the best practice of having an unidirectional data flow and controlled components in your application. You don’t want to reference the elements in order to get their values. You want to keep the state at one place as single source of truth in your local state.

What about functional stateless components?

Often functional stateless components are not mentioned regarding the ref attribute. Maybe it is because these components have no this object. They are stateless. Yet you can use the ref attribute with a variable.

function SearchForm({ onSearch }) {
    let input;
    return (
        <div>
            <input
                ref={node => input = node}
                type="text"
            />
            <button
                onClick={() => onSearch(input.value)}
                type="button"
            >
                Search
            </button>
        </div>
    );
}

Afterward, like in the example above, you can get the value of the input element and propagate it in the callback up to the parent component.

After all, often you have to refactor a functional stateless component to an ES6 class component, because you need the DOM node reference in a lifecycle method that is only available in a stateful component. For instance, consider you want to focus an input element when the component mounted.

class FocusedInput extends Component {
    componentDidMount() {
        this.input.focus();
    }

    render() {
        return (
            <input
                ref={node => this.input = node}
                type="text"
            />
        );
    }
}

Don’t bother that the input component is useless in the example. It is only a focused input element. It doesn’t handle any input value or onChange() event. But that’s sufficient for the sake to showcase the ref attribute.

Still, you are able to see the difference compared to a stateless functional component where you don’t have access to lifecycle methods. Hence you have to refactor components, depending on your use case, to ES6 class components to apply your desired behavior.

After all, you can use the ref attribute in ES6 class component and in functional stateless components in React.


I hope the article gave you some clarification on how, when and where to use the ref attribute to reference DOM nodes in React.

Build a Hacker News App along the way. No setup configuration. No tooling. No Redux. Plain React in 190+ pages of learning material. Learn React like 12.000+ readers.

Get the Book
comments powered by Disqus

Never miss an article about web development and self-growth.

Take Part

Join 7200+ Developers

Learn Web Development with JavaScript

Tips and Tricks

Access Tutorials, eBooks and Courses

Personal Development as a Software Engineer