Access a component's underlying DOM node with findDOMNode()
Tags: webdev, javascript, tutorial, react
Published: 2023-12-02 09:34:03

When working with React, we often use the virtual DOM instead of the real DOM because updating the virtual DOM is much faster than updating the real DOM directly. However, there are times when we need to access the real DOM node. For example, we may need to measure its dimensions or apply a third-party library that requires direct manipulation of the DOM. In these cases, we can use the `ReactDOM.findDOMNode()` method to get a reference to the underlying DOM node for a given component instance.

Although `findDOMNode()` was commonly used in the early days of React, it is now **deprecated** and not recommended for use in modern React applications. However, we still introduce it in this series to provide a complete understanding of React ref.

## Understanding the syntax

The `findDOMNode()` function in React is straightforward. It only requires one parameter, which is the component you want to access the DOM node of.

```js
import * as ReactDOM from 'react-dom';

ReactDOM.findDOMNode(component);
```

Let's see the function in action. We'll create a component that automatically fits content of a text area. Exciting stuff! Let's dive into the next section.

## Automatically resizing text areas

Auto-resizing text areas are a great feature for many real-life situations. For example, in comment sections on websites, users often write comments of different lengths. If the text area is fixed, it can be challenging to write or read longer comments. With an auto-resize feature, the text area can expand as the user types, making it more comfortable to write and read comments. As a result, there can be more engagement and discussion on the website.

Another use case is in forms where users need to provide input that may vary in length, such as feedback or descriptions. An auto-resize text area can make it easier for users to provide their input without feeling limited by a small text box. With auto-resize, users can write as much as they need to, making the process smoother and more enjoyable.

We're creating a component called `AutoResizeTextarea` that will resize the text area element to fit its initial value. We'll use the `componentDidMount()` lifecycle method to call the `fit()` function when the component is first mounted. This ensures that the textarea is sized correctly from the start. Don't worry, we'll go over the `fit()` function soon.

```js
class AutoResizeTextarea extends React.Component {
    componentDidMount() {
        this.fit();
    }

    render() {
        return <textarea></textarea>;
    }
}
```

In this component, the `fit()` method is responsible for resizing the textarea to fit its content. First, it grabs the DOM node using `ReactDOM.findDOMNode(this)` and sets its height to `'auto'`. This tells the browser to calculate the necessary height based on the content of the textarea.

```js
fit() {
    const textarea = ReactDOM.findDOMNode(this);
    textarea.style.height = 'auto';
}
```

Next, we need to figure out the border width at the top and bottom of the textarea. To do this, we retrieve the computed styles of the textarea and pass the border width values to the `parseValue()` method.

```js
const styles = window.getComputedStyle(textarea);

const borderTopWidth = this.parseValue(styles.borderTopWidth);
const borderBottomWidth = this.parseValue(styles.borderBottomWidth);
```

`parseValue()` is a helper method takes a CSS value as a string and returns its integer value in pixels. If the value ends with `'px'`, we convert it to an integer using `parseInt()`. Otherwise, we return 0 as the default value.

```js
parseValue(v) {
    return v.endsWith('px') ? parseInt(v.slice(0, -2), 10) : 0;
}
```

Once we have the border width values, we add them to the calculated height of the textarea before setting it as its new height. This ensures that the entire content of the textarea is visible without any overflow or cropping due to borders.

```js
fit() {
    // ...
    textarea.style.height = `${textarea.scrollHeight + borderTopWidth + borderBottomWidth}px`;
}
```

Resizing the text area automatically as users change its value is a piece of cake. We simply need to handle the `input` event that triggers whenever users modify the value, and call the `fit()` function within the handler.

```js
class AutoResizeTextarea extends React.Component {
    handleInput(e) {
        this.fit();
    }

    render() {
        return <textarea onInput={this.handleInput}></textarea>;
    }
}
```

Let's take a look at how we can use the component we created earlier:

{% codesandbox k3n7z6 %}

## Limitations of findDOMNode()

`findDOMNode()` is **no longer recommended** for use in modern React applications due to its limitations. One of its limitations is that it can only be used on class components, not functional components. This means that if you're using functional components, you'll need to switch to class components or find another way to access the underlying DOM node.

Another limitation is that `findDOMNode()` can only be called after a component has mounted. If you need to access the DOM node before it has mounted, you'll need to find another way to do so.

Using `findDOMNode()` can also lead to performance issues because it breaks the separation between the virtual DOM and the real DOM. When we update the virtual DOM, React uses a diffing algorithm to determine which parts of the real DOM need to be updated. However, when we use `findDOMNode()`, we bypass this algorithm and directly manipulate the real DOM, which can lead to unnecessary updates and slower performance.

Finally, `findDOMNode()` only gives access to the root DOM node representing the component. If you want to access different elements within the component, you'll need to find another solution. In the next post, we'll discuss an alternative solution using string refs.

---

It's highly recommended that you visit the [original post](https://phuoc.ng/collection/react-ref/access-a-component-underlying-dom-node-with-find-dom-node/) to play with the interactive demos. 

If you found this series helpful, please consider giving the [repository](https://github.com/phuocng/master-of-react-ref) a star on GitHub or sharing the post on your favorite social networks 😍. Your support would mean a lot to me!

If you want more helpful content like this, feel free to follow me:

-   [Twitter](https://twitter.com/_phuocng)
-   [GitHub](https://github.com/phuocng)