In the flux architecture, who is responsible for sending updates to the server?
Asked Answered
F

2

1

So in the flux architecture, data flows as follows:

View -> Action -> Dispatcher -> Store
 ^ <-----------------------------|

So let's say the view is a comment box. When the user submits a comment, an addComment action is triggered, but where should that comment be sent to the server? Should it happen in the action function, before dispatching it, or should the store doing it when receiving the action from the dispatcher?

Both cases seam like a violation of the single responsibility pattern. Or should there be two CommentStores, one LocalCommentStore and a ServerCommentStore that both handle the addComment action?

Fewness answered 8/11, 2014 at 12:1 Comment(0)
F
6

In your case Action is responsible for both sending a pending action or optimistic update to the store and sending a call to the WebAPI:

View -> Action -> Pending Action or optimistic update  -> Dispatcher -> Store -> emitEvent -> View 
               -> WebUtils.callAPI()

onWebAPISuccess -> Dispatcher -> Store -> emitEvent -> View
onWebAPIFail -> Dispatcher -> Store -> emitEvent -> View
Fowlkes answered 8/11, 2014 at 12:26 Comment(1)
Thanks for your answer, but how should caching be done in this case? Should information like the expiration date be stored in the Store? Or should WebUtils somehow handle this?Fewness
B
4

This is a great question. Here is how I do it.

I create a module for my API. I import that module in actions.js, then dispatch the API responses to my store. Here is an example (uses fluxxor) of what the store with my API calls in my application may look like:

# actions.js
var MyAPI = require('./my-api'),
    Constants = require('./constants/action-constants');

module.exports = {
    doSomeCrazyStuff: function(stuff, userID) {
        MyAPI.doSomeCrazyStuff(stuff, userID)
             .success(function(resp) {
                 this.dispatch(Constants.DO_CRAZY_STUFF_SUCCESS, {stuff: resp.stuff});
                 if (resp.first_stuff_did) {
                     this.dispatch(Constants.SHOW_WELCOME_MESSAGE, {msg: resp.msg});
                 }
             })
             .error(function(e) {
                 this.dispatch(Constants.DO_CRAZY_STUFF_ERROR, {e: resp.error});
             });
    }
};

# store.js
var Fluxxor = require('fluxxor'),
    ActionConstants = require('./constants/action-constants');

var StuffStore = module.exports = {
    Fluxxor.createStore({
        initialize: function() {
            this._bindActions();
            this.stuff = null;
        },
        _bindActions: function() {
            this.bindActions(
                ActionConstants.DO_CRAZY_STUFF_SUCCESS, this.handleDoCrazyStuffSuccess
            );
        },
        handleDoCrazyStuffSuccess: function(payload) {
            this.stuff = payload.stuff;
            this.emit('change');
        }
   });
}

# stuff-component.js
var React = require('react'),
    Fluxxor = require('fluxxor'),
    FluxMixin = Fluxxor.FluxMixin(React),
    StoreWatchMixin = Fluxxor.storeWatchMixin;

var StuffComponent = module.exports = React.createClass(function() {
    mixins: [FluxMixin, StoreWatchMixin("StuffStore")],
    getStateFromFlux: function() {
        flux = this.getFlux();

        var StuffStore = flux.store("StuffStore").getState();

        return {
            stuff: StuffStore.stuff
        }
    },
    onClick: function() {
        this.getFlux().actions.doSomeCrazyStuff();
    },
    render: function() {
        return <div onClick={this.onClick}>{this.state.stuff}</div>
    }
});
Brouhaha answered 18/12, 2014 at 7:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.