Skip to content

React Context value propagation performance  #13739

Closed
@alexreardon

Description

@alexreardon

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)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions