Alex Sidorenko AvatarAlex Sidorenko

16 Nov 2021

A Visual Guide to React Rendering - Refs

How can we disable this button after 3 clicks without re-rendering the component for the first 2 clicks?

<button disabled={count === 3}>Button</button>

Storing values with refs

When you want a component to “remember” some information, but you don’t want that information to trigger new renders, you can use a ref—it’s like a secret “pocket” for storing information in your component!

React Docs - Referencing Values with Refs

Let's try counting clicks with refs instead of state.

<button disabled={count.current === 3}>Button</button>

The ref updates, but the button is still active. Why is that?

Component renders and DOM updates

For React to disable the button, it needs to update the DOM. React updates the DOM when a component renders with different output than before. React won't update any DOM until one of its components renders. Since changing a ref doesn't cause the component to re-render, the button stays active.

To demonstrate this point further, let's add a parent component.

By default, when you render a React component, it recursively re-renders all its children. That's why when we update the Parent state, it renders both Parent and Component. When Component renders, React executes the condition and disables the button.

<button disabled={count.current === 3}>Button</button>

However, we can't rely on parent updates to disable a button. Let's implement this behavior directly in Component.

Update state to re-render a component

We can make the component re-render by reintroducing state. But we still don't want the component to render on the first 2 clicks. So we'll keep the ref to silently count the clicks, and we'll add a state variable with the sole responsibility of updating the button status. Let's update buttonStatus only when the button is clicked for the third time.

<button
disabled={buttonStatus === 'disabled'}
onClick={() => {
count.current++
if (count.current === 3) {
setButtonStatus('disabled')
}
}}
>

This example demonstrates the behavior of refs. Keep in mind that unnecessary renders aren't always bad, and you don't have to eliminate every one of them. In fact, in a real-world scenario, it would probably make more sense to rely solely on state and re-render this component 3 times for simplicity. However, you'll encounter various situations in your apps. Understanding refs gives you a powerful tool for fine-tuning the behavior of your components.


Follow me on 𝕏 for short videos about Next.js

𝕏 Follow for more