-
Notifications
You must be signed in to change notification settings - Fork 49.1k
Description
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.