question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

React Context value propagation performance

See original GitHub issue

Hi there!

I have observed a performance issue with context providers and value updates. I have spoken with @gaearon with this on twitter, so he will have a bit more context

Let’s say you have a provider:

const CounterContext = React.createContext(1);
const Provider = ContextContext.Provider

And you update the value to the provider

render() {
  return (
    return <Provider value={this.state.value}>{this.props.children}</Provider>
  )
}

All good so far.

Let’s say you want to pass this value down the tree, but for performance reasons you do not want to render the tree. The only components you want to render are your consumer components (in our case CounterContext.Consumer)

A naive way would be to do something like this:

class Blocker extends React.Component {
  shouldComponentUpdate() {
    return false;
  }
  render() {
    return this.props.children;
  }
}

// ...

render() {
  return (
    <Provider value={this.state.value}>
	 <Blocker>
          {this.props.children}
     </Blocker>
    </Provider>
  )
}

Even though no components in the tree are rendered except for the consumers, the update itself is very expensive. I suspect that the tree walking algorithm takes a while to run.

Standalone example

https://codesandbox.io/s/61jnr811kr

This example has about a 20-30ms render time for a simple counter update. In a production app with a list of 500 nodes (~500 * 10 components, 5000 components) we were looking at update times similar to that of rendering the tree (150ms+)

A bit more context

I was trying to replace react-redux with a root StateProvider that would create a subscription to a store and pass the latest state into the context. The consumers would then pick up this update, run a selector, and re-render if the result value had changed. I had this all working in react-beautiful-dnd but I found the updates through the context itself was too slow for usage (You can see the relevant files here and here)

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:33
  • Comments:35 (18 by maintainers)

github_iconTop GitHub Comments

14reactions
abritinthebaycommented, Dec 5, 2018

We could also have a linked list of all context consumers. That’s still a traversal to do but it’s less than the whole tree.

Is this something that is likely to be on the roadmap soon? Given React-Redux has just released its new context subscription model I imagine you’ll be hearing more about perf issues related to this…

13reactions
markeriksoncommented, Nov 15, 2018

I have to say this is still my biggest concern about moving React-Redux to use createContext internally. Still not sure exactly how much it’s going to affect things in real-world apps, but it does seem like there’s definite overhead involved in traversing the tree to find consumers.

Read more comments on GitHub >

github_iconTop Results From Across the Web

An Introduction To Context Propagation In JavaScript
“Context provides a way to pass data through the component tree without having to pass props down manually at every level.” — React...
Read more >
Context - React
All consumers that are descendants of a Provider will re-render whenever the Provider's value prop changes. The propagation from Provider to its descendant ......
Read more >
How to write performant React apps with Context
React re-renders everything for no reason when you use Context! ... here: when the value in an input changes, we propagate this value...
Read more >
React Context API: A deep dive with examples - LogRocket Blog
As with prop drilling, there can be some performance drain when using Context. Whenever it renders, its child components also render. One way...
Read more >
React context, performance? - DEV Community ‍ ‍
I can't have a better definition than in the documentation: Context provides a way to pass data through the component tree without having...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found