DEV Community

Joseph Mawa
Joseph Mawa

Posted on • Edited on

Lazy state initialization in functional components.

This brief post will focus on lazy state initialization when using useState hook. If you don't know what useState hook is, you can read about it in my introductory article on useState hook Here.

If you want to initialize state in functional components, you can use useState hook. This hook takes the initial state as its argument and it returns an array of two entries. The argument passed is set as the initial state.

const[state, setState] = useState(1)
Enter fullscreen mode Exit fullscreen mode

Sometimes instead of passing a primitive value, an object or an array as argument, you can also pass a function. The value returned by the function passed is used for initializing state.That is referred to as lazy state initialization. Lazy state initialization is necessary if you are performing a computationally expensive process for initializing state. Consider the example below:

import React from "react";

function initializer() {
  return Math.random();
}

function App() {
  const [state, setState] = React.useState(initializer());
  const clickHandler = React.useCallback(() => {
    setState(prev => prev + 1);
  }, []);
  return (
    <div className="App">
      <h1> {state} </h1>
      <h2>
        <button onClick={clickHandler}> Click </button>
      </h2>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

In the example above, initializer is defined outside the component. It returns a random number which is used for initializing state. The initial state is ignored in subsequent renders but the function initializer which is used for initializing it is invoked in every re-render. This might not be a big problem if you are simply returning a random number like in the above example however it causes performance problems if initializer performs a computationally expensive process.

How do we get over this problem?

To solve the problem described above, you can pass a function which calls initializer as an argument, like:

 const [state, setState] = React.useState(() => initializer());
Enter fullscreen mode Exit fullscreen mode

or else pass initializer to useState without invoking it like:

 const [state, setState] = React.useState(initializer);
Enter fullscreen mode Exit fullscreen mode

The above two approaches ensure initializer is invoked on first render but ignored in subsequent re-renders.

Thanks for reading this article to the end. If you found it informative, consider sharing it on twitter or any other social media platform. Others might find it useful too.

References

Top comments (0)