Back to overview

How to optimize your context value

March 8th, 2021 3 min read

by Paweł Czerwiński
by Paweł Czerwiński
No translations available.Add translation

NOTE: Before we get started, I want to make sure you know the times it's important to optimize your context value is when a certain combination of the following conditions are met:

  1. Your context value changes frequently
  2. Your context has many consumers
  3. You are bothering to use React.memo (because things are legit slow)
  4. You've actually measured things and you know it's slow and needs to be optimized

If that explains your situation, then read on (and don't miss the alternative solution which is honestly probably better anyway). In fact, the alternative is definitely better and I've reworked the blog post to remove my original recommendation and just show the alternative. If you want to see my original, read the original stuff here.

No seriously, if you're going to do this stuff just because you think your code might be slow, then don't bother. I'm not joking. React is really fast and adding complexity in the name of performance when performance is good enough is just wasteful of your "complexity budget"

The simplest solution to optimizing your context value involves using useReducer or useState for your state management and putting the state in one context provider and the dispatch in another. Here's that:

Not only do you not need to useMemo in this case, but you actually can avoid re-rendering the components that just use the updater context:

clicking "force render" three times and "Increment count" twice

This is the same as with my original useMemo solution, except because the <Counter /> component's context isn't getting updated, we avoid the re-render of that component entirely which is cool.

I personally feel like this is more complicated of an API than is necessary for most situations, so I wouldn't bother optimizing most of my contexts. But if you really have all the problems mentioned above, then consider doing this as a simple way to side-step the issue.

The state and dispatch separation is annoying

Some people find this annoying/overly verbose:

const state = useCountState()
const dispatch = useCountDispatch()

They say "can't we just do this?":

const [state, dispatch] = useCount()

Sure you can:

function useCount() {
  return [useCountState(), useCountDispatch()]
}

Just keep in mind that any component that uses that, you will lose the performance benefits if it only needs one or the other.

Also, don't miss How to use React Context effectively.

Kent C. Dodds
Written by Kent C. Dodds

Kent C. Dodds is a JavaScript software engineer and teacher. He's Co-Founder and Director of Developer Experience at Remix! Kent's taught hundreds of thousands of people how to make the world a better place with quality software development tools and practices. He lives with his wife and four kids in Utah.

Learn more about Kent

Want to learn more?

Join Kent in a live workshop

If you found this article helpful.

You will love these ones as well.