3

For example, say I have two separate lists of items on a page. Perhaps we're ordering from a pizza and sub shop.

  • List 1 - Food Type - Pizza, Sub
  • List 2 - Condiment - Lettuce (Sub only), Onions (Both), Anchovies (Pizza only)

I have two separate reducers that track the selected items in list 1 and 2.

Say the user has Pizza and Anchovies selected, but decides he'd rather have a Sub. He switches his selection and an action is dispatched to update the foodType reducer. How does the condiment reducer become aware of this?

I see two possible solutions, but both are flawed.

I can listen to the FOOD_TYPE_CHANGED action in both reducers, and, assuming there's some additional computation necessary, also compute the new food type in the condiment reducer so the two don't need to be directly aware of each other. Of course this is redundant, but there's another issue with it as well. Let's say there's a third list that depends on the condiment selection. Do we now have to also listen to FOOD_TYPE_CHANGED and compute both foodType and condiment here? We can extend this concept out perpetually and it continues to get more complicated.

I can compose these into a single reducer and handle the interaction between the two at a higher level. But say I have a complex application with not just two, but ten pieces of interdependent state. This approach seems like it would get hairy very fast and not really serve to simplify anything as it scales.

Are there better ways to handle this type of situation?

Adam Arthur
  • 409
  • 3
  • 10

1 Answers1

0

This is a pretty common question. Remember that reducers are just functions - you can feel free to organize them however you want. You can put more logic into an action creator, and pass the needed "other branch" data in the action; you can combine reducers; you can write a more "manual" top-level reducer rather than using combineReducers(), and pass the other branch as an additional argument to a sub-reducer, etc. See the discussion at Redux issue #749: Best practice for updating dependent state across different branches of the state tree? for some further thoughts.

markerikson
  • 63,178
  • 10
  • 141
  • 157
  • Thanks for the response. I've read that thread and others on this same topic, but maybe I'm just having a hard time wrapping my head around it. If I use a top level reducer doesn't that inherently couple foodType and condiment? If I need condiment in a different context where foodType is irrelevant, wouldn't I need to create a separate "parent" reducer to handle that case, thus duplicating the state in the tree? – Adam Arthur Jan 14 '16 at 23:26
  • I realize it's just an example, but it certainly does seem as if there's SOME amount of coupling between "condiment" and "foodType" right now. So, it's reasonable that there be SOME code that handles that. The `reduceReducers()` sample at https://github.com/rackt/redux/issues/749#issuecomment-164327121 is an interesting approach. It lets you use the more common `combineReducers()` for most of the "independent" action handling, but add some additional logic for the more "coupled" actions. – markerikson Jan 14 '16 at 23:40
  • Hmm that may be exactly what I need for my use case! I guess I overlooked the implementation there. Certainly the two are coupled to some extent, but does any light coupling necessitate they go in the same reducer tree? For my real app almost all of the data is "lightly" coupled to some extent, but using a single giant reducer tree, or multiple actions to handle this seems unsavory. I guess I'm still in the "observable" mindset (in my case angular) where I can simply watch the foodType and react to changes without having to be aware of specific actions performed against it. – Adam Arthur Jan 15 '16 at 01:09