MeteorFlux Flow

Here you go: MeteorFlux AppState

It doesn’t depend on Dispatcher, so you can use it without Flux.

If I add more stuff, it will be with options, so it won’t affect the default behaviour.

It is difficult to answer. If you are using an object-tree, then the Stores as “classes” lose sense. They become just functions which mutate state. Redux does a good job explaining this.

In Flux views should only render the app state. But as many things, it depends on the component and how it is going to be used. I think unless you want to share it with the rest of the world like a black-box component, then logic should go outside.

If different parts of your app are going to be able to play, pause or stop videos (for example) that functionality should be in a Store which controls their state. The component should only care about the rendering part, it shouldn’t care if a menu has been opened and the video should pause, for example. Only -> state: “paused”. Then -> state: “playing”.

I was glad to see this post, it reminded me I wanted to take a look at flux

so I made a very basic pattern to do flux in the meteor way and explain stateful declarative approach to those who are only just getting there

http://fluxstate.meteor.com/

thatnks @luisherranz for your meteorflux packages - they make things easy

No problem :smile:

That’s really great, thanks for contribution. I’d have a couple of comments if you want my opinion.

hey @luisherranz, I’d really value your opinion

I love it so far, especially this:

// Init app
const handle = Meteor.subscribe('user');
AppState.set('initializing', function() {
  return !handle.ready();
});
1 Like

That’s neat. Good example!

With the new Dispatcher version (1.1.0) the dispatcher accepts an string as first argument:

Template.circuit.events({
        'click #switch' : function () {
            Dispatcher.dispatch('CIRCUIT_TOGGLE');
        }
    });

Note that it will be added to type instead of the old actionType (yep, we switched to Redux style, it’s simpler).

For Stores, I wouldn’t create them inside Templates. I will create a folder and individual files for each one of them.

Then, inside stores/circuitStore.js I would do:

// Set default state needed by this store using the MeteorFlux AppState package.
AppState.set('circuit.closed', false);

Dispatcher.register(function(action) {
  switch (action.type) {
    case 'CIRCUIT_TOGGLE':
      let currentState = AppState.get('circuit.closed');
      AppState.set('circuit.closed', !currentState);  // reverse state.
      break;
    }
});

// Link states using Tracker
Tracker.autorun(function(){
  let meta = AppState.get('circuit.closed') 'light on' : 'light off';
  AppState.set('circuit.meta', meta);
});

Note here we changed to payload.actionType to action.type. Again, it’s Redux style.

Then, with AppState you don’t need to create a helper anymore. You can just use {{#if circuit.closed}} and {{circuit.meta}} wherever you want.

Doing it this way the code you need is reduced significantly.

If you want to test this code just dispatch "CIRCUIT_TOGGLE" and test the state with AppState.get. You don’t need access to the function itself.

1 Like

Oh, and if you use the new Dispatcher Helper package you can dispatch directly from Blaze.

This will work exactly like your code:

<a href='#' data-action-type='CIRCUIT_TOGGLE'>
  <svg width="600" height="400" id="svg2">
        ...
  </svg>
</a>

: )

I was working from previous stuff I’d done, and I stuck your dispatcher and AppState into what I’d roughly be doing with my own solution. Part of my thinking in putting them inside the template,

  • architectural simplicity, fitting into the exiting Meteor model that everyone knows
  • ensure they are available when needed
  • access to the template instance
  • to use other aspects, e.g. data model, parents and so on (although this may be wrong headed in terms of flux)
  • also, to lock the store into the template

So, i’d be interested in your thoughts about that.

Quick question on this: this is defined globally, correct? Is there any way to have app states that are specific to a particular store?

If you are using react with meteor, is it recommended to still use session variables or just use the original redux since it is react compatible?

So with this Flux architecture, does it make more sense to subscribe to publications in the AppState then? E.g.:

AppState.set('appointments', {
  handle: Meteor.subscribe('appointments'),
  dataReady: this.handle.ready(), // this is probably wrong - how do we refer to handle?
});

Also, previously we had to set up getters like so:

let appState = new ReactiveDict();
[...]

Store = {
  getSomething() {
    return appState.get('something');
  }
};

But with AppState, I assume that’s no longer the case, as you can just access that directly (AppState.get).

Yes, AppState is meant to be global and hold all the state of the app in a unique object tree. The concept is similar to Baobab, NuclearJS or Redux, but prepared to play nice with Meteor reactivity, Mongo cursors, Blaze…

If you want to keep the state local to the stores, you can use things like local ReactiveVar, ReactiveDict, the excellent ReactiveObj object of @xamfoo, the upcoming Store class of @gunnarsturla or even local copies of AppState created using MeteorFlux:

var circuitState = new MeteorFlux.AppState();

A good practice of other flux frameworks using a single state object is to store only the smallest amount of state possible so I wouldn’t store the whole handle.

Yes, AppState gives you both a getter and a Blaze helper automatically.

I am not sure really. Maybe @SkinnyGeek1010 can answer you better because he has been testing Redux and React inside Meteor.

If you want to use the MeteorFlux Dispatcher and AppState packges instead, this example of @ffxsam shows you how:
https://github.com/ffxsam/meteorflux-test/blob/master/client/components/Timer.jsx

If your subscription depends on the application state (i.e. is part of the business logic), then I think you should subscribe in your Store (or whatever name you call the place where your business logic is).
If your subscription depends on the template (i.e. you need those data now for displaying in this template), then I think you should use template-level subscription.

@luisherranz: Is there any difference or advantage to using AppState.get('timer.running') vs the below:

timerState = new MeteorFlux.AppState();

then in a component: timerState.get('running')

The Blaze helper name would be {{running}} and not {{timer.running}}.