Search code examples
javascriptreactjsflux

Does accessing information returned from an action creator in a component break Flux?


When performing an action in a component does it break the Flux pattern to access the promise returned from the action creator within the component?

Action Creators

class MyActionCreators extends Marty.ActionCreators {
  create() {
    this.dispatch(MyActionConstants.CREATE_ACTION);

    return MyActionAPI.create()
      .then(res) {
        this.dispatch(MyActionConstants.CREATE_ACTION_DONE);
        return res;
      };
  }
}

Compoment

class MyCompoment extends React.Component {
  render() {
    return(
      <div>
        <button onChange={ this._clickAction }>Create Me!<button>
      </div>
    );
  }

  // private
  _clickAction() {
    MyActionCreators.create()
      // Does this break Flux?
      .then((res) => {
        this.context.router.transitionTo('some_path', { id: res.id });
      });
  }
}

Are stores the only appropriate place to access this information required in the example above?


Solution

  • Answer

    This does break Flux because it moves state away from a store and has the action directly communicating with the view.


    A possible solution

    Making some assumptions on your system, I am going to assume you have a single router that you are trying to update.

    Note: Examples are not complete, they just give the basic idea. They are also not based on any implementation of the Flux architecture.

    The Store

    Create a store that will contain the id. The store must emit some sort of change event.

    Example

    var Store = function() {
        this._id;
        Dispatcher.on(MyActionConstants.CREATE_ACTION_DONE, function(payload) {
            this._id = payload.id;
            this.emit("change");
        }.bind(this));
    }
    
    Store.prototype.getId = function() {
       return this._id;
    }
    

    The Controller-View

    Create a controller-view (similar to your react component) that will update the router based on a change in the store.

    Example

    var store = new Store();
    store.on('change', function() {
       router.transitionTo('some_path', { id: store.getId() })
    });