Skip to content

Efficiently ignore irrelevant updates from context #12876

@aldendaniels

Description

@aldendaniels

We're using context to represent where user focus is in a large app. In our app, we have many (hundreds) of "Focus Routes" that listen to the focus location in the app - much like routes in React Router.

Most focus transitions are irrelevant to most routes - some routes lose focus and some gain it, but most are unaffected. Today we have a context consumer at each route component that computes some derived state (e.g. isFocused, etc.) and provides that derived state as props to a wrapped component. The wrapped component has an optimized shouldComponentUpdate().

The problem we're hitting is that React appears to do a meaningful amount of work every time the context consumer is re-rendered, even though the wrapped component doesn't re-render. This adds up quickly across all the focus routes. Our next step is to do better profiling on in production mode, but on dev it appears to be ~0.5ms per route, which is problematic.

What we need is a way to efficiently prevent subscribers from re-rendering when the new value (focus location in our case) isn't relevant. The unstable_observedBits feature is almost right for us, but the the 32bit limitation is unsuitable for our scenario. If this were an unbounded list of booleans, for example, we could use this to only update invalidated components. Alternatively, if a ContextConsumder took a shouldComponentUpdate() hook we could use that.

Consider this a plug for a a non-32-bit restricted alternative to unstable_observedBits :)

If nothing like this is forthcoming, we'll likely revert to using an emitter/subscriber model in a batched update. This is non-ideal for us, however, because there's state that we need to propagate to new components in a single render pass and context is particularly good at this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions