4 ms·
There are two problems with React which I see at the moment: 1) Layouting 2) (more to the point of this article) what if your app isn't composed as a tree? More
by xixixao 13y ago
There are two problems with React which I see at the moment: 1) Layouting 2) (more to the point of this article) what if your app isn't composed as a tree? More specifically, what if I have two tightly coupled components in two different places (physically and hence in the DOM), which need to share state? I don't want to have to go through a massive tree all the way to the root just to get that information between the two components work.
I also want components which are reusable and some of this information flow make tight coupling between parents and children. There are certainly things to be figured out, React is no silver bullet.
- acjohnson55 13y agoIn a large Backbone project, I experienced this issue. Many people solve the problem with an event bus. To me, that makes debugging a huge pain and coupling rather difficult to analyze. I solved it by passing a single flat context object that provides the API exposed by all of the ancestors of a component. Components can either pass this context unmodified to their children or make modified copies to add to the API seen by their children. The advantage here is that intermediate layers of the tree don't need to know about APIs they don't directly consume, solving the problem of making every intermediary component mediate communication between parent and child. As for the somewhat more difficult problem of allowing distant parts of the app to communicate (say, A and B), the key is abstracting objects for holding application state and communicating changes across the app into a new component C, which must be held by a common ancestor D of A and B. D then becomes responsible for mixing C's interface into the context object received by all its children. Typically D should be a controller-type component, mostly existing to serve as the nexus for a subsection of the app. D might also be the top level app object. But partitioning concerns into separate components like C avoids bloating D, and yields a lot of flexibility. Other interesting patterns can be done as well. Optional hooks can be defined as context methods. The flat namespace of the context object also acts like a facade, decoupling the consumer of API methods from the actual provider. By making every member of the context a function (as opposed to data members), late coupling is achieved, which I found very useful in simplifying initialization dependencies. On the whole, I found the flat context to be extremely flexible, and developed a number of patterns for solving particular problems. I have an unfinished blog post on the topic that I may one day get around to.
- kylemathews 13y agoPlease do finish the post, this is a hard problem.
- sbrekken 13y agoI'm using the exact same flow in my current project. Shared data is stored in the state of a single component. Data propagates via props and since you've got a single source of truth you don't have to worry about data synchronization. To manipulate data, the component that owns the data exposes methods to children via context. As a bonus, components become incredibly easy to test since both props and context are both explicitly passed to each component.
- masklinn 13y ago> More specifically, what if I have two tightly coupled components in two different places (physically and hence in the DOM), which need to share state? Pass the same state to both? The application state and the render state don't have to be trivial mappings of one another.