Architecture V2
We started slowly migrating from the container pattern describe in Architecture V1 to a provider pattern using React context. This allows components at any level of the tree to access props directly without needing to pass props down on every level.
There are API and feature modules that manage their own state. Feature modules own components specific to that feature. All reusable components live in the component library.
Context Problems and Pain Points
The context API (providers) pattern has been abused for convenience and to avoid prop drilling which has resulted in certain issues.
Component reusability
When a context provider is wrapped over multiple components, we implicitly pass whatever state or data that is stored in that provider to the children components it wraps. This makes testing a lot harder and integration with Storybook difficult.
Performance
The Context API uses a comparison algorithm that compares the value of its current state to any update it receives, and whenever a change occurs, the Context API broadcasts this change to every component consuming its provider. This in turn results in a re-render of these components. If the re-rendered component is high up in the tree then all it's children are re-rendered as well.
This would seem trivial at first glance, but when we rely heavily on Context for basic state management, we over-engineer our application by needlessly pushing all of our states into a context provider. As you'd expect, this isn't very performant when many components depend on this Context Provider, as they'll re-render whenever there is an update to the state regardless of whether the change concerns or affects them or not.