9

I have my own opiniated way on how to use React and am building my own framework, inspired by Om. I am implementing something a bit similar to the Flux architecture, with stores that can update themselves on some events.

What I am not sure to understand is why in the Flux architecture do we need store dependencies?

Stores aren't supposed to be self-contained data holders for a given bounded context, like we do with CQRS architectures?

In an evented system, 2 CQRS components could end up holding the same data. Do we express store dependencies to avoid holding duplicate data in stores?

Can someone come up with some very concrete use cases where store dependencies are needed and where the problem can hardly be solved in any other way? I can't find any myself.

Sebastien Lorber
  • 89,644
  • 67
  • 288
  • 419
  • Where did you end up on this? – bentayloruk Jun 10 '15 at 10:19
  • 1
    @bentayloruk check https://github.com/stample/atom-react . Also Dan Abramov is experimenting store composability instead of dependency (I somehow do this too). See https://gist.github.com/gaearon/d77ca812015c0356654f – Sebastien Lorber Jun 10 '15 at 12:21

2 Answers2

4

In refluxjs we solve waitFor in a couple of ways, one for the sequential data flow and the other for the parallel data flow. I try to model the data stores in a way to avoid holding the same data (i.e. double maintenance data).

Basically, data stores are CQRS components, and I try to avoid having 2 data stores end up with the same kind of data. If I need to transform the data somehow that only some components need, I break that out to an "aggregate" data store. Naïve implementation:

var carsStore = Reflux.createStore({
    init: function() {
        this.listenTo(Actions.updateCars, this.updateCallback);
    },
    updateCallback: function() {
        $.ajax('/api/cars', {}).done(function(data) {
            this.trigger(data.cars);
        }.bind(this));
    }
});

We can create another data store that aggregates the data by listening to the carsStore:

var modelsStore = Reflux.createStore({
    init: function() {
        this.listenTo(carsStore, this.carsCallback);
    },
    carsCallback: function(cars) { // passed on from carsStore trigger
        this.trigger(this.getModels(cars)); // pass on the models
    }
    getModels: function(cars) {
        return _.unique(_.map(cars, function(car) { return car.model; }));
    }
});

That way your React view components may use one to get the cars and the other to get the models, which is aggregated from the carStore.

If a store needs to wait for two parallell data streams to complete we provide the Reflux.all to join actions and stores. This is useful e.g. if you're waiting for data to load from seperate different REST resources.

var carsAndPartsAreLoaded = Reflux.all(carStore, partsStore);

// you may now listen to carsAndPartsAreLoaded 
// from your data stores and components

Hope this makes sense to you.

Spoike
  • 119,724
  • 44
  • 140
  • 158
  • We will be looking into making CRUD commands easy to handle in reflux against offline local storage and adaptor for a web api. This will most likely become an extension, as refluxjs core may be used server-side (in NodeJS). – Spoike Aug 11 '14 at 14:30
  • I think duplicating the data is actually the solution to not have any dependency between Flux stores and to not have to deal with store synchronization thus. What do you think of this? http://msdn.microsoft.com/en-us/library/bb245672.aspx – Sebastien Lorber Aug 11 '14 at 20:12
  • @SebastienLorber Why do you feel the need to **not** have dependencies between stores? One of the pain points Facebook tried to alleviate with Flux was to avoid dealing with transitive data in components, which was a major source of bugs (according to the video). Synching data within the web application is solved automatically in Flux by signalling or passing around the data in a *predictable uni-directional flow*. – Spoike Aug 12 '14 at 06:31
  • Sorry but I don't understand what you mean by `transitive data between components` nor which part of which video you refers to. I think making autonomous stores is also very predictable as the store events become the source of truth and it scales better on large codebase, as when developing one component, you don't need to understand how other components work but just the business events that can be fired. In your Flux design, tell me it never happens that you want to refactor one store and have to refactor another store as a side effect? – Sebastien Lorber Aug 12 '14 at 10:23
  • @SebastienLorber Oops. I meant "derived data", they're discussing this with a use case in the [video](http://facebook.github.io/react/docs/flux-overview.html) around 14:00-17:00 mins. I think we're on the same page regarding the store events "becoming the source of truth". In reflux you wire up the components (stores and react components alike) by subscribing to events on actions or other stores. They will receive the event data from a store rather knowing what it does internally and you're not supposed to know the exact interface of the stores you're listening to. – Spoike Aug 12 '14 at 14:45
1

I've finally built an application with something akin to Flux stores without any dependency.

Recently Dan Abramov created a framework (Redux) that highlights flux stores composability, without the need of any store dependency or waitFor, and I share most of his ideas

Sebastien Lorber
  • 89,644
  • 67
  • 288
  • 419