Lazy state initialization `React.useState`

Lazy state initialization `React.useState`

·

2 min read

The hooks API has been nothing less than a revolution in the React world. No more dealing with the complexities of the Javascript class, nor the crazy React lifecycle methods 🤮.

Hooks opened up more user-friendly ways to create highly reusable logical components.

In an attempt to hone my React hooks skills I have taken up the epicreact.dev course and tried to delve a bit deeper into each of the native hooks provided and found a few interesting quirks about a few of them. Today I would like to share one about the React.useState API.

As a seasoned React developer is familiar by now, the React.useState, provides for us a way to maintain the state in a functional component between renders. This can be seen in a very simple example below,

image.png

The highlighted line shows the classic usage of React.useState API which takes an initial value and returns a current value and an updater function. When the component re-renders due to a state change (in this case the count aka state is changed on the click of a button) the highlighted portion of the code is re-run, however, the initial value is ignored and the updated value is set to be the current value.

We can ascertain the above by getting the initial value via a function and logging each time it re-renders the same

image.png

Here is the real bummer, if our initial value function is computationally expensive, this would mean every time our component re-renders the expensive computation also takes place, just to be ignored by React 🤦🏻‍♂️. This can hamper the performance of our component as well.

Lucky for us the React.useState API also provides for lazy evaluation of initial value. Lazy evaluation can be achieved by passing a reference to the function to be evaluated rather than passing the evaluated value as seen in the example above. The reference to the function is evaluated by React only during the initial render and ignored in the subsequent renders, thus providing for us a bit of performance gain 🥳.

image.png

On an ending note, I would like to mention that, the lazy initialization is to be used only in cases where the initial value computation is expensive. In the most common scenarios where we have a direct value assigned to React.useState, using direct initialization is preferred as creating a function wrapper is also an overhead.

Cheers!