jmreidy / fluxy

An implementation of Facebook's Flux architecture
232 stars 19 forks source link

Add an example of a React mixin to the documentation #10

Open nicolashery opened 10 years ago

nicolashery commented 10 years ago

I noticed that a lot of boilerplate in my React components listening to stores is the wiring up in getInitialState, componentDidMount, componentWillUnmount. For example:

var AccountPage = React.createClass({
  getInitialState: function() {
    return assign({
      working: false
    }, this.getUserStoreState());
  },

  componentDidMount: function () {
    UserStore.addWatch(this.handleUserStoreChange);
  },

  componentWillUnmount: function () {
    UserStore.removeWatch(this.handleUserStoreChange);
  },

  handleUserStoreChange: function(keys, oldState, newState) {
    if (keys !== 'user') {
      return;
    }
    this.setState(this.getUserStoreState());
  },

  getUserStoreState: function() {
    return {
      user: UserStore.loggedInUser()
    };
  },

  //...
});

Would it be worth coming up with a React mixin for that, and including it in the documentation and/or examples for people to use in their own apps?

kballenegger commented 10 years ago

For what it's worth, here's my mixin:

 var _ = require('lodash');

var StoreReactivityMixin = {
  componentDidMount: function storeReactivityComponentDidMount () {
    var onChange = this._storeReactivityMixinRefresh;
    this._storeReactivityMixinEachStore(function (store) {
      store.addWatch(onChange);
    });
  },
  componentWillUnmount: function storeReactivityComponentWillUnmount () {
    var onChange = this._storeReactivityMixinRefresh;
    this._storeReactivityMixinEachStore(function (store) {
      store.removeWatch(onChange);
    });
  },
  _storeReactivityMixinRefresh: function storeReactivityMixinRefresh () {
    this.setState({storeReactivityMixinLastRefresh: (new Date).getTime()});
  },
  _storeReactivityMixinEachStore: function storeReactivityMixinEachstore (fn) {
    _.each(this.reactToStores, fn);
  },
};

module.exports = StoreReactivityMixin;

And here's how it's used:

var SomeComponent = React.createClass({
  mixins: [StoreReactivityMixin],
  reactToStores: [SomeStore],

  render: function() {
    // ...
  }
});

module.exports = AuthGate;
jmreidy commented 10 years ago

Yeah, I'm increasingly starting to come around to making this a part of Fluxy directly. @kballenegger, I like your idea of tracking the refresh time...

nicolashery commented 10 years ago

Thanks for sharing @kballenegger! Simple and effective :)

kballenegger commented 10 years ago

@jmreidy - I'd be happy to pull request it into the Fluxy source, if you'd like me to.

jakecraige commented 10 years ago

I've swapped out the _storeReactivityMixinRefresh function with this to match closer to the initial example.

  _storeReactivityMixinRefresh: function() {
    var args      = arguments;
    var component = this;
    this._storeReactivityMixinEachstore(function(store) {
      var handler = component['handle' + store.name + 'Change']
      typeof handler === 'function' && handler.apply(handler, args);
    });
  },

So that the component can respond to each store's change with a function. In the mixin example case, you could define a handleSomeStoreChange method that would be called with the changes