Michael Michael - 2 months ago 19
Javascript Question

Should I structure the Redux store after the domain or after the app views?

I'm trying to wrap my head around Redux and how to implement it in a React Native app.

I get the general idea and I like it. But I'm not quite sure how to structure my store. I'll try to give an example with two scenes from the app.

ProjectListScreen:
A list of projects built with a ListView component. Each row exposes about 5 fields from each project object.

ProjectScreen:
A ScrollView showing all fields for a specific project. The project object can be quite large and not entirely flat. For example it holds an array of UUIDs pointing to images.

So, should I have a single reducer to handle the complete "Projects" or should I have one reducer for ProjectList and one for Projects? I.e. should I think in terms of the real domain or in terms of views/screens in the app?

I suspect that the answer will be to mimic the domain. But what if there are 1000 projects in the list? I need to load 1000 projects into the store including all fields for each project. But I will only need five of those fields to render the ListView. Only a couple of projects will probably be loaded fully because the user won't open all 1000 projects in a ProjectScreen. A change in one project will force a copy of the while array in order to stay immutable.

I don't want to get stuck in premature optimizing, but I'd like to get the structure of the store somewhat right from start. I know I could use Immutable.js to optimize the updating of items in the list, but this would give me non JS objects to work with, which feels kind of cumbersome.

I'd rather use seamless-immutable, but I don't think this kind of partial update of a large list will be faster with SI than copying the list.

I'd love to hear that performance will be a non-issue compared with the UI rendering and other tasks. This would make it a no-brainer to go with a domain structure.

Answer

Domain, absolutely. Your store structure should totally reflect the actual data you're working with. Your UI layer should then do any transformations needed on a per-component basis, primarily in your mapStateToProps functions. Focus on the actions and behavior that make up your application at its core. (This should also lead to a better testing setup as well.)

The best practice for organizing data that is nested or relational is to normalize it, similar to tables in a database. I've written some prior answers that describe this concept to some extent, and link to some further articles and discussions ( [0], [1], [2] ).

I generally advise against using Immutable.js, at least to start with. It has its uses, and can offer some performance improvements if your app is configured correctly, but also has a number of potential performance pitfalls as well ( [3] ). I would suggest sticking with plain JS objects. There's a variety of ways to use those in an immutable fashion. I have a list of articles describing those approaches ( [4] ), as well as a list of libraries that can make immutable use of plain JS objects easier ( [5] ).

Finally, I'm actually just starting to work on a new page for the Redux docs that describes best practices for structuring reducers. It'll take some time to get it written and polished, but you might want to keep an eye on it. The issue is at [6], and that has a link to my current WIP article branch.

[0] http://stackoverflow.com/a/38105182/62937
[1] http://stackoverflow.com/a/38017227/62937
[2] http://stackoverflow.com/a/37997192/62937
[3] https://github.com/markerikson/react-redux-links/blob/master/react-performance.md#immutable-data
[4] https://github.com/markerikson/react-redux-links/blob/master/immutable-data.md
[5] https://github.com/markerikson/redux-ecosystem-links/blob/master/immutable-data.md
[6] https://github.com/reactjs/redux/issues/1784

edit:

As a follow-up, the Redux docs now include a "Structuring Reducers" section, which has a variety of information on this topic.