spoike
9/4/2014 - 6:37 AM

Simple WebAPI example

Simple WebAPI example

Prefice

Gist posted in reply to this jsbin snippet for the comment at Deconstructing Flux post.

In my mind you really should have a single kind of interface for what gets passed on through this.trigger from a Data Store. In the jsbin example, you're sending both errors and posts, which is not really "single-kind" in my mind. So what if we could split this up into two seperate concepts... why not two seperate data flows?

So if you want to handle errors, then you're better off creating a seperate data flow for that (i.e. start with an error action) so that components that do error messaging specifically use that instead.

The application will look a little like this crude ASCII art:

Actions      Stores           Components
-------      ------           ----------
load ------> postsStore ----> <PostList />
                 |
    +------------+
    v             
loadError -> errorStore ----> <ErrorMessage />

Hope this helps!

var PostsApi = require('webapi/posts'), 
        // assuming the api object from the jsbin snippet
    Reflux = require('reflux');

var PostActions = createActions(["load", "loadError"]);
        // load action is invoked either from:
        // * top most component's componentDidMount 
        //   function in your application, or
        // * window.onLoad
        // I prefer the first strategy because that'll
        // ensure that the React application has loaded 
        // properly

var postsStore = Reflux.createStore({
    init: function() {
        this._posts = [];
        this.listenTo(PostsActions.load, this.loadPosts);
    },
    loadPosts: function() {
        PostsApi.getPosts()
            .done(this.onLoad) 
            .fail(this.onLoadError); 
    },
    onLoad: function(posts) {
        this._posts = posts;
        // May need to use ImmutableJS here instead to 
        // make sure the components don't accidentally 
        // change this array leading to weird heisenbugs
        this.trigger(this._posts);
    },
    onLoadError: function(error) {
        PostActions.loadError(error);
        
        // OPTIONAL depending on requirements. Pass on an
        // empty array in case components shouldn't show
        // posts if an error happened
        this._posts = [];
        this.trigger(this._posts);
    },
    getDefaultData: function() {
        // To handle components using listenTo's third argument
        // introduced in Reflux 0.1.7
        return this._posts;
    }
});

var errorStore = Reflux.createStore({
    init: function() {
        this.listenTo(PostActions.loadError, this.trigger);
        // just a shortcut (pass on the error message to the listening
        // components), just to avoid having components listen to the 
        // action directly
        
        // This enables us to refactor the error flow later to do 
        // more complex error handling, but for now we assume the
        // error handling components in our application use the error 
        // message that comes from the PostsApi
        
        // Suggestions include handle error messaging state
        // (for when to show and hide error messages), or
        // handling list of error notifications (clearing error 
        // messages, etc.)
    },
    getDefaultData: function() { return ""; }
});