For example, if I have a login reducer and a user icon reducer. When I login, I want to update the user icon as well as storing the user's info. I am stuck between two choices:
First one is to export the USER_LOGIN action and have both login reducer and user icon reducer handle USER_LOGIN action.
Second approach is to have a 1 to 1 mapping between action and reducer (one type of action belongs to only one reducer). We have login reducer handle USER_LOGIN, then with Saga/Thunk we dispatch a side effect UPDATE_USER_ICON to the user icon reducer.
Which one is a better practice ? I personally favor the second approach.
Quoting the Redux FAQ entry on dispatching multiple actions:
There's no specific rule for how you should structure your actions. Using an async middleware like Redux Thunk certainly enables scenarios such as dispatching multiple distinct but related actions in a row, dispatching actions to represent progression of an AJAX request, dispatching actions conditionally based on state, or even dispatching an action and checking the updated state immediately afterwards.
In general, ask if these actions are related but independent, or should actually be represented as one action. Do what makes sense for your own situation but try to balance the readability of reducers with readability of the action log. For example, an action that includes the whole new state tree would make your reducer a one-liner, but the downside is now you have no history of why the changes are happening, so debugging gets really difficult. On the other hand, if you emit actions in a loop to keep them granular, it's a sign that you might want to introduce a new action type that is handled in a different way.
Try to avoid dispatching several times synchronously in a row in the places where you're concerned about performance. There are a number of addons and approaches that can batch up dispatches as well.