Optimizing Initial State in React with useState

Optimizing Initial State in React with useState
Photo by Lautaro Andreani / Unsplash

Saw this on X.

Approach 1. Avoid this.

const [selection, setSelection] = useState(getInitialSelection());

In this example, getInitialSelection() is invoked immediately when the component renders, regardless of whether the value is needed or not. This can lead to inefficiencies because the function will run every time the component re-renders, even though the initial value is only required during the first render.

Approach 2. Prefer this.

const [selection, setSelection] = useState(getInitialSelection);

In this preferred approach, getInitialSelection is passed as a reference (without parentheses), meaning React will only invoke the function once, during the initial render, when the state is first initialized. Subsequent renders will not re-execute this function, making it more efficient.

Why the second approach is better

  • Lazy Initialization: React's useState can take a function as an argument, which will only be executed during the initial render. By passing getInitialSelection without calling it, React defers the execution until it's needed, improving performance, especially if getInitialSelection is a complex or resource-heavy function.
  • Avoid Unnecessary Recomputations: In the first example, getInitialSelection() runs on every render, which is unnecessary and can cause performance issues, especially in components that re-render frequently.

This pattern is useful when the initial state calculation is expensive, and you want to ensure it's only done once, when the component mounts.

Why this matters

At first glance, the difference between getInitialSelection() and getInitialSelection might seem subtle, but in a larger, more complex application, it can make a big difference. For simple components with static initial values, this issue might not be noticeable. But as your app grows, especially when your state initialization involves API calls or complex logic, avoiding redundant function calls can have a significant impact on your app’s performance.

Efficient state management is key to keeping your React components lightweight and responsive. By deferring the execution of initialization logic to the first render only, you avoid unnecessary work, freeing up resources and improving the user experience.

Finally

When you initialize state in React using useState, passing a function reference instead of calling the function immediately is a simple but effective optimization. It ensures that any complex logic or data fetching only happens once—when the component is first rendered—saving your app from needless re-renders and performance bottlenecks.

By leveraging lazy initialization, you’re not only following best practices but also making your components more scalable and efficient. So next time you’re working with useState, consider how you initialize your state and take advantage of this small but powerful optimization technique.

Support Us