3 ms·
Author here. I worked with different domain models using Redux, and also different codebase sizes, and it finally led me to this library. Originally I was inv
by bloomca 9y ago
Author here.
I worked with different domain models using Redux, and also different codebase sizes, and it finally led me to this library.
Originally I was involved into building data layer for collections (e.g. how Netflix shows list of series), and I was building a very complicated factory to produce kind of the same thing -- actions, reducer and selectors, with aggressive caching and normalizing.
Later I worked with less amount of entities, and more RPC style APIs (a lot of interaction with user, which are pretty much bunch of requests, where you track pending state, error and success -- think about reset password, obtaining a token, etc). When you have not so many entities, normalizing becomes not so necessary, but I have noticed couple of things which are constantly used and were giving me pain points:
- tracking async code (e.g. dispatching start, failure and success)
- universal approach to caching (each action creator often had slightly different caching mechanism)
- nesting results (e.g. put `terms` under `documents` reducer)
- because of verbosity I personally tended to combine a lot of logic under a single action (so sometimes several raw API requests were made from a single action, not just dispatching other actions)
I have tried to address all of these issues here. The idea is pretty simple -- the library creates a so-called "tile" with everything: actions, reducer, constants and selectors, allowing you to nest it in the state (so you can easily separate let's say `user` part), and to nest results, universal approach to caching (all async requests are aggressively cached, so if you dispatch the same action, it will wait the already made request, and you can safely await returned promise). Also, I expose function back, so it is much easier to test it, in case you inject all dependencies to the middleware (I personally like it, but seems that it is an anti-pattern).
And the last thing -- in case you instantiate middleware for each request on the server side, you get back `waitTiles` function, which after dispatching all needed actions will return you a promise, awaiting which will give you fully resolved tiles. So, you can do dry run of the react render on the server, wait for tiles, and then safely render again, knowing that everything in `componentWillMount` under the render path will be fetched.
This SSR part still has few questionable parts, but I feel it is a good idea in general (I want to write a post about possible scenarious, how to prefetch for SSR).
In case you have any questions, or just want to chat about different approaches in reducing boilerplate size for Redux, I'd be glad to answer!
- tarr11 9y agoHappy to see people trying to solve this problem. Can you talk about how this compares to redux-saga?
- acemarke 9y agoPretty sure they're solving very different problems. redux-saga is about managing side effects using generators, particularly in response to dispatched actions. redux-tiles is largely about abstracting the logic for creating and dispatching actions and applying nested updates in reducers.
- bloomca 9y agoThanks! As @acemarke mentioned, they are really different (and there is nothing to stop you from using them together, if you want -- tiles expose constants). Even if you use redux-saga for all side effects, you would still have to write some redux code, e.g. for `usedLoggedIn`, and even it is the easiest action and reducer, it will take from you about 30 LoC. And usually we tend to group reducer hanlders together, combining only the higher level (so, usually there is only `user`, but only in case of big amount of actions we will separate `userAuth`). So, I've tried to make it as easy as possible to nest them (so you would use type like `['user', 'auth']`), and to nest data under let's say ids. You don't have to think about it -- there is just a little amount of magic under the hood, which will nest it, merge data and combine reducers. So, saga adresses side effects problem (especially when they are pretty complicated, and depend on each other), while this library provides some sugar on top of raw redux "ducks".