Building my own Store object


#1

I’ve run into a situation in this app I’m working on where I really need to have certain objects at the highest level (such as a modal component) that other components anywhere in the hierarchy can call upon. I don’t really understand how Flux and Redux work, despite looking at the documentation—or I should say, I don’t understand how to make it work in the context of Meteor. So I thought, why can’t I just make my own really simple global Store object?

I tried it, and it seems to work just fine. What I’m doing is creating a mixin that I use in my main Layout component, which provides all the global actions. So for instance:

Layout = React.createClass({
  mixins: [ReactMeteorData, GlobalActions],

  componentWillMount() {
    Store = this;
  },

And then:

Store = {};

GlobalActions = {
  getDefaultProps() {
    return {
      actions: {
        showModal(message, buttons, callback) {
          Store.setState({
            modalMessage: message,
            modalButtons: buttons,
            modalVisible: true,
            modalCallback: callback
          });
        }
      }
    }
  },

  getInitialState() {
    return {
      modalButtons: ['OK'],
      modalMessage: '',
      modalVisible: false,
    }
  }
};

And then in Layout at the bottom of render():

<Modal visible={this.state.modalVisible}
       message={this.state.modalMessage}
       buttons={this.state.modalButtons}
       callback={this.state.modalCallback} />

So then any component, no matter where it is, can do something like this:

this.props.actions.showModal(
  'Some message.',
  ['OK'],
  this.userClickedBtn
);

Oh and last but not least, this is the Modal's button click handler:

handleButtonClick(buttonLabel) {
  this.props.callback.call(null, buttonLabel);
  Store.setState({modalVisible: false});
},

After all, it looks like Flux and its relatives are sort of doing the same thing, just creating a global store. So is there anything wrong with this approach, then? I just don’t think I have the time to dedicate to learning Flux or Redux. Maybe if there a neat/clean Meteor package that bundled up Redux and made it super simple to use, I might go that route. But in the mean time, my semi-hacky solution seems to do the trick. Unless there are potential gotchas? :slight_smile:


#2

Just giving you a hard time :laughing:

I think rolling your own flux may work but you’ll run into issues later that will be harder to sort out.

Have you tried the new Redux docs? They’re much better than they were a while ago. Also you can code along in the first part right in the console as there isn’t any view layer.

This first example app should only take 5-10 mins to get a fully functioning Redux counter app :smiley:
Section 2 adds action creators which are optional but help abstract things out of the view.


[quote="ffxsam, post:1, topic:10035"] Maybe if there a neat/clean Meteor package that bundled up Redux and made it super simple to use, I might go that route. [/quote]

Checkout this repo (Redux branch) and try to modify/add some buttons to it:
https://github.com/AdamBrodzinski/meteor-flux-leaderboard/tree/redux

Note, this also is storing minimongo data in Redux which is not necessary. It’s likely easier use this with just local state (like the currently selected player part).

Also the redux time-travel debugger added a bit of extra junk in the bottom of store… this needs a conditional for dev/prod. that I need to add in soon.


#3

Haha! Nice GIF :smile:

I think I breezed too quickly through the Redux docs last time. I’ll have to de-clutter my brain, sit down with some caffeine, and go through it. I think I got discouraged because it was mostly code snippets and I didn’t know how to incorporate it with Meteor and React. But I noticed in later sections it talks about how to wire it into React.

Some of this stuff is challenging to me since I skipped over a lot of JS stuff (Node, CommonJS, DI, etc).


#4

Read the docs again, they’re pretty good and you can stop when you hit middleware and come back later :wink: you should be up & running with easy redux stuff pretty quickly, it’s more of a pattern (or, not really, a way of thinking maybe) than actual code.

If you’re using Immutable.js you might want to check out this one:

As already mentioned, If you’re not then check flux-helpers:

For now I don’t mind duplicate data, it’s not like I have problems with memory or anything. But up until now I haven’t used this in bigger production apps.


#5

Yea no kidding! I wish there was a book that laid it all out but the frontend JS stuff changes so rapidly.

Hooking up to react is pretty simple once you get the hang of it. Basically you have your single object of state and you just tell it to map ‘viewersStuff’ key on that state to a ‘viewer’ key on props. Then inside your component you can refer to that as ‘this.props.viewer’. You can slice off as much or as little of this global state object as you’d like.

Example:

const AppContainer = React.createClass({
  render() {
    return (<App {...this.props} />);
  }
});

// choose what slice of state we send to the component & it's children
function mapStateToProps(state) {
  return {
    players: state.players,
    selectedId: state.userInterface.selectedId,
  };
}

this.AppContainer = connect(mapStateToProps)(AppContainer);

Hehe, yea think of middleware as optional!