React/Flux - Why do I need a action-dispatcher?
Asked Answered
W

1

7

I understand that I need a emit.change() dispatcher, to let all components know that something changed inside the store. But I dont understand why I need to dispatch actions rather than calling stores directly from inside the actions,

.i.e. why should I do this:

var Dispatcher = require('dispatcher');
var MyActions = {
    addItem: function(item){
        Dispatcher.dispatch({
              action: 'ADD_ITEM',
              payload: item       
       })
    }
}

rather than this:

var MyStore = require('mystore');
var MyActions = {
    addItem: function(item){
        MyStore.addItem(item);
    }
}

Is that for the case that multiple stores listen to the same event, for example when StoreA and StoreB listen to ADD_ITEM as well?

Westernmost answered 10/12, 2015 at 13:58 Comment(0)
Y
9

The dispatcher fires actions one by one, when they are called. You need a dispatcher because:

  1. You want the application state to be changed atomically. Which means, s1->s2(a1), s2->s3(a2) in a synchronous manner. Rather than s1->s3 (because of a1 and a2). If you don't do it, you will have to worry about other actions firing along with this particular action and guess how the application state will change for all those combinations. This is where all hell breaks loose and your code will become too difficult to maintain. Imagine writing an if-else block in the store for each action fired, to check if other actions are also active . The dispatcher makes sure that it does not dispatch while already dispatching. One dispatch at a time. Keeps your state tree very healthy.

  2. Also the dispatcher maintains an array of callbacks to fire for each 'action'. This is useful for calling callbacks on multiple stores for the same action. When a store subscribes to an action (using register), the dispatcher adds the registerHandler associated with it and adds it to an array. With the help of this, you can register/unregister your stores when you need them. And depending on the action type, you can make changes accordingly to all the stores registered. If you don't use a dispatcher, you will have to worry about all the stores which have to notified, when you are writing the action part. Bad!

  3. With this kind of approach, the only thing you have to focus on, is hitting the dispatcher with an action. The rest is upto the dispatcher which notifies all the stores which need to change based on the action. Since the stores have callbacks which trigger the views, those callbacks can be called as and when needed. This keeps your code very modular.

Yawning answered 10/12, 2015 at 14:6 Comment(7)
Thanks for the great answer! I have another question related to that, which is why I came to this question here in the first place. I need to return a value (the ID of a newly created item) from an action and pass it to the next action. Should I dispatch the next action including the ID from within a Store rather than dispatching multiple actions after other? The other question is hereWesternmost
The best thing to do would be to use the same action and listen on both the stores for it, and make changes accordingly. Actually, there is always a way to do it. You just have to tweak your code a little bit. You dispatch with this {data_for_store1: {...},data_for_store2:{...},action:'ADD_ITEM'} and both stores can now use the same action. Does this help?Yawning
That was what I was doing at first, but action1 creates a new ID in StoreA and I need to pass that newly created ID somehow to to StoreB. Can this be done via modifying the dispatcher, so that I can return values after dispatch?Westernmost
In that case, you will probably have to fire another action. I would not suggest modifying the dispatcher, rather modify the actions and the stores. If one store needs data from the other store, then probably, both the stores should be combined into one store. Split stores on a different basis rather than on this. Just giving you ideas.Yawning
due to the complexity of the data model combining them into one store is not possible unfortunately. Would it be a bad advice to fire the other action from within StoreA? And thanks a lot for your fast help! :)Westernmost
If that is the case, then you should fire the action from the store. Its not a great idea, but if it works, then thats all that counts. However, just make sure you don't end up in an infinite loop ie., Action->Dispatch->Store->Action.Yawning
Let us continue this discussion in chat.Westernmost

© 2022 - 2024 — McMap. All rights reserved.