DEV Community

Kartik Sharma
Kartik Sharma

Posted on

⚛️ Why Conditional Initial Values Don’t Always Work with useState

React components re-render whenever their props change — but how that affects internal state can be tricky.

Take this snippet I came across yesterday while reviewing one of my older projects:

const [options, setOptions] = useState(selectedOptions ? selectedOptions : []);

Enter fullscreen mode Exit fullscreen mode

At first glance, the logic seems fine:

“If the selectedOptions prop exists, use it; otherwise, start with an empty array.”

It works — but only if the parent component sends the correct selectedOptions on the very first render.

Now imagine the parent fetches that data asynchronously (say, from an API). On the initial render, it passes an empty array — and later, once the API resolves, it sends the real selectedOptions.

Here’s where things break.

Even though React re-renders the child component when the prop updates, the state won’t reinitialize.

Why?

Because useState only uses its initializer on the first render.

The mindset behind this line —

“Whenever the component receives a new selectedOptions prop, re-instantiate this state.”

— isn’t how React actually works.

React recalculates your JSX on every render, but it does not re-run the initializers for hooks like useState. That initial value is locked in after the first mount.

This is precisely why useEffect exists — to respond to changing props and synchronize internal state accordingly.

The correct approach looks like this 👇🏼

useEffect(() => {
  if (selectedOptions) {
    setOptions(selectedOptions);
  }
}, [selectedOptions]);

Enter fullscreen mode Exit fullscreen mode

This version reflects the right mindset:

“Whenever selectedOptions changes, update the options state to match it.”

That’s the real difference — not in the code, but in how you think about React’s lifecycle.


So that’s my take on this topic — something I rediscovered while reviewing my past work and reflecting on how I used to approach logic building.

Remember, learning a language or framework goes far beyond just syntax. Syntax can be mastered in days or weeks, but developing the mindset — the psychology behind how a framework actually thinks and behaves — takes time. It only comes from running into those tricky edge cases and “aha” moments that challenge how you reason about code.

Thanks for reading! 👋🏼

Top comments (0)