Reputation: 4698
I'm working on re-writing/porting my huge slideshow project to React and Redux, which used to be a big jQuery project with business logic stored in large classes.
I'm going to dive straight into my problem.
I have three Redux reducers, actions and middlewares:
The feeds middleware takes care of fetching new posts, and storing them in feed.posts
The slideshow reducer maintains a lot of state about the slideshow itself, and business logic, e.g. which post it's currently displaying, what post should come next in, etc. It should also maintain a list of posts that have been filtered, e.g. there should be no posts that have been blocked.
The problem I'm facing is this:
The feeds middleware dispatches an action with new posts, and then the feeds reducer stores the posts in feed.posts
. That's all fine. But now I want the slideshow reducer to process the posts, to remove posts that have been blocked, etc, and then store them under slideshow.posts
, while the feeds.posts
will always contain the raw post list for other purposes.
My current solution basically to catch the new posts action in the slideshow middleware, and from there I dispatch a new action with the new posts, which can then be processed in the slideshow reducer. This feels anti-pattern; using a middleware to dispatch an action so that it can be processed in a different reducer.
Another solution would be to dispatch two actions in the feeds middleware when new posts are available:
dispatch(feedNewPosts(posts))
dispatch(slideshowNewPosts(posts))
This way I can get rid of the middleware hack, but it also feels anti-pattern.
Then I thought about using selectors, the slideshow container would select the posts and filter them by the blocked list, etc. But the problem I'm facing with that solution is that I need to know which posts have been blocked in the slideshow reducer because most of the business logic for the slideshow happens in there.
Here's an example:
The slideshow middleware dispatches an action to show the next slide, dispatch(slideshowNextSlide())
.
The slideshow reducer handles the action and checks which slide should be displayed next, and stores that slide in the state as slideshow.nextSlide
, add flags to the post for animation purposes, etc. So based on that, I need access to the filtered posts in the slideshow reducer.
So if this was all handled by complex selectors, then I won't have all the information I need in the state, e.g. which slide should come next, so that I can add the correct animation classes, etc.
Is there something obvious I'm missing? Perhaps I'm trying to have too much information stored in the state, but I love the idea of having the complete state of the slideshow in the state, e.g. if I want to save the slideshow state and load it later, etc.
The slideshow container and component would be really dumb, just display whatever is in the state, add certain animation classes if the post matches slideshow.nextSlide
and so on. No complex selectors.
Any help in the right direction would be highly appreciated.
Thanks.
Upvotes: 2
Views: 798
Reputation: 47279
It is perfectly fine for two reducers to listen to the same action. That is one of the benefits of redux
: A certain event happening on your application might be interesting for more than one component, and you don't want them to be aware of others.
So triggering a second action would be an anti-pattern. I would aim to raise a single action:
dispatch(newPosts(posts))
and then you could have both the feed
and the slideshow
reducer listening to the same action, and modifying their part of their state accordingly.
I think in this case it is important to separate the abstract action that is happening in your system (new posts are available based on the result of an API call or something else) from the reducers that are going to listen to it. If you do that, having one action that modifies two different slices of the state feels much more natural.
Upvotes: 2