Skip to content

Instantly share code, notes, and snippets.

@amannn
Last active July 25, 2016 08:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amannn/89b8f4e1c52541d323c574fcb5a80b83 to your computer and use it in GitHub Desktop.
Save amannn/89b8f4e1c52541d323c574fcb5a80b83 to your computer and use it in GitHub Desktop.

Hi!

I'm writing here, as this probably doesn't fit within a tweet :).

I was working on a bigger redux app not too long ago, where I had a lot of entities with relationships in between. The "store layer" was mostly concerned with fetching data, storing them, providing ways to create/update/delete them via REST and in more sophisticated scenarios optimistic updates, cancelling duplicate requests when data was fetched just recently or currently being fetched and paginating through lists.

As there is usually no special logic in regards to the type of an entity, I was trying to put together an abstraction layer for the actions, the reducers and the selectors so that doesn't have to be repeated all the time.

For data from endpoints like /user (only 1 instance) or /books (a list) this has worked quite well, but it became somewhat complicated with nested entities that have relationships. My wrapper offered a configuration to specify what kind of entities are related in what way (either 1:1, 1:n or n:m; e.g. books/author, books/translations or /books/related, …) and lists should also keep track of the sorting and implement pagination. I got a prototype working, but later figured I'd rather load related data directly in the React components as there was now quite a heavy layer of abstraction and I wasn't sure if I had the best solution.

I was somewhat wondering at that time that there's not much information about such scenarios out there, as I think this is a somewhat common use case. One of the more sophisticated libs was redux-orm at that time, but it was pretty young, so I didn't use it (I think it also didn't support all my use cases at that point, not sure though). Your docs would have definitely come in handy at that point for inspiration :).

You're definitely making a good point by saying it helps to create more connected components when you have nested normalized data. It was somewhat cumbersome creating all the necessary data from its normalized form to pass them to deeply nested views.

One more problem I was thinking about, was that as my REST endpoints didn't respond with nested data and I had to fetch every entity seperately, the views would re-render continuously when data arrives in pieces over time (probably this could have been solved though). I then thought I should just go for GraphQL and stop with my research on how to solve this with redux.

I think your docs do a great job of explaining the theories behind the necessary topics, I guess I'd just needed a good library that implemented all of this with a good API :).

One thing you maybe could add though, is that it can be helpful to store meta data about the loading state of the entities in the store. I've used something like {state: loadingStates.LOADED, lastUpdated: 123456789, error: null}. I've seen the twitter mobile app uses something like {hasLoaded: true, isFetching: false, hasError: false} – the state of these keys imply the state of other keys, but I think their approach is better than mine, as there's no concept of enums in JavaScript and so it's easier to consume by views. The lastUpdated field also allows to implement app-level caching. Later I also added {lastSuccessfullySubmitted: {…}} for rollbacks after failed optimistic updates.

Overall, I really have to say you did a great job on improving the docs! This is by far the most inspiring work I've seen covering more advanced redux topics. And the state shape is from my experience the most important thing to get right. If you have that figured out, the remaining parts of the redux architecture are usually the easy part from my experience. Really great job :).

Sorry for the long text, maybe there's something in here that helps you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment