Reputation: 205
I have a general architectural react-redux question whether to use sub-app approach or not.
At the moment we're developing a generic list/detail view. For the list-view, we retrieve the data with redux-saga and save them to the redux store and connect them to the list component. On paging/search we trigger an action that refreshes those data. A requirement is, that the detail-view can contain list-views of related records (sub-list). The root list-view and the sub-list are visually almost the same, except maybe a search form should not be visible by default and and actions should work differently (only retrieve related data, row-click should not show detail in sub-list...)
To solve this I can think of two solutions:
-1- Reuse Components, share store
We can reuse the list-view container. With a dynamic amount of sub-lists we have to store the data with an id in the store. On paging etc. we have to replace the correct dataset. Garbage Collection has to be handled manually.
-2- Sub-App Approach
As described here: Isolated Subapps We could create an isolated component of the detail/list-view. If we want to have a subgrid we simply include this component. This would be the same as we use for the rootlist-view.
Pro/Cons
For the subapp I see advantage in autonomy. The data could be kept in a separate store and we don't have to implement something "id-based" in the store. We can destroy the subapp and the store is removed as well. On the downside, some data is being retrieved on root level und since we don't want the sub-app to do the same REST call to get those, we need to find a way to send these informations to the sub-app. And a row-click probably has an effect on the root view (redirect) So the sub-app needs to send data and get data of the root element and is therefore not as isolated as I wish.
Does anyone made some valuable experience with any approach? Any feedback would be greatly appreciated!
Upvotes: 2
Views: 1407
Reputation: 6944
Where I work, we have 2 large web application that share some functionality. They are developed by 11 distinct teams, across 4 geographical locations.
We decided to break the sites down into logical sub-apps (dubbed "micro-frontends") where a single team is responsible for it's development. So being as decoupled as possible from the parent apps was important to us (redux helps out a log with this in general).
Some sub-apps would be used in both sites, which made autonomy a huge issue (there was no guarantee the parent apps would construct the stores in the same composition as each other, and we didn't want to enforce them to have to).
Some other sub-apps didn't need to be in both sites, but did need to be displayed in multiple locations on the same site, with different data (similar to your case).
Most sub-apps also had to display their data in context of what the parent app had selected or use the logged in security token for API requests, so being able to access the root store was also important.
We also had an idea to capture analytics and logging through redux middleware, so having a single store to wire all that up in was a benefit to us as well.
As you can probably tell by now, we wanted all the benefits of both approaches and so we created redux-subspace with a "why not both?" philosophy.
In the end, we used it to not only achieve all the goals listed above, but we also started breaking down the sub-apps even further and having sub-apps composed of multiple sub-apps to further isolated specific features.
The core concept is to have a single store but create isolated sections (subspaces) for your sub-apps. There is functionality for accessing the root store values as well.
So you could do something like
<Provider store={store}>
<SubspaceProvider mapState={(state) => state.list1}>
<ListView />
</SubspaceProvider>
<SubspaceProvider mapState={(state) => state.list2}>
<ListView />
</SubspaceProvider>
</Provider>
Where list1
and list2
are the locations in the store for 2 different data sets.
The main thing to note about the ListView
component is that it should now maps its state as if the provided node is the root of the store and access root values through the root
node.
e.g.
Before subspace:
const mapStateToProps = state => {
return {
myList: state.list1.items
rootValue: state.rootValue,
}
}
After subspace
const mapStateToProps = state => {
return {
myList: state.items
rootValue: state.root.rootValue,
}
}
Note: There is a namespacing feature for actions, but does not support redux-sagas (yet). It can namespace actions dispatched from within the subspace though, so this may or may not be an issue for you (depends on implementation details of your app).
Disclaimer: I am the main contributor on redux-subspace.
Upvotes: 7