Skip to main content

Command Palette

Search for a command to run...

Why you should avoid using the effect>setState pattern in React

... and what to replace it with

Updated
3 min read
Why you should avoid using the effect>setState pattern in React
P
I am a full-stack developer specializing in React, Next.js, TypeScript, C#, .NET and Sitecore. I love working on back-end as well as front-end, writing documentation, finding solutions to problems, and writing technical blog posts to help others. I've been Sitecore certified and Coveo for Sitecore certified twice.

Let's say you have an initialItems array that you fetch from an API and set it in state like this:

const [items, setItems] = useState<T[]>(initialItems)

You may instinctively realize, initialItems is only set as the default value of this state, so items won't update when initialItems changes, and you'd be right. If the initialItems passed to your component or hook is fetched from an API and later changes, items won't reflect it.

To resolve this issue, you may reach for an effect, so that the items state is updated when the fetched data changes:

useEffect(() => {
  setItems(initialItems)
}, [initialItems])

Stop right there! There's a much simpler way to do this that doesn't require an effect and is recommended by the React team.

Why you shouldn't use an effect here

React has published a doc titled You Might Not Need an Effect. In summary, it explains that effects aren't necessary in most cases and are used frequently in use cases where the code would perform better without one. You may read the article for yourself, but I want to highlight the Adjusting some state when a prop changes section. It states:

Every time the items change, the List and its child components will render with a stale selection value at first. Then React will update the DOM and run the Effects. Finally, the setSelection(null) call will cause another re-render of the List and its child components, restarting this whole process again.

Essentially, calling an effect to update a list in state causes more unnecessary re-renders, which we should always try to avoid when working with React.

The simple fix

In our case, and as shown by the article, we can replace the effect that calls setItems with the following. Place this after your useState call in your code:

  if (initialItems !== items) {
    // Update the state variable when `initialItems` changes
    setItems(initialItems)
  }

So on every render of your component or hook, this conditional simply checks if the prop has changed from the initial value the state variable was given, and updates state in that case. No useEffect necessary and no unnecessary re-renders.

Conclusion

I thought this post would be a useful, quick read for any other developers that find themselves often reaching for the useEffect -> setSomeState() crutch, as I have. That entire article from the React team is really useful to understand when and when not to use effects and I recommend reading it.

12 views