reflux / refluxjs

A simple library for uni-directional dataflow application architecture with React extensions inspired by Flux
BSD 3-Clause "New" or "Revised" License
5.36k stars 330 forks source link

Single Page State Pattern for Reflux+React #429

Closed souptown closed 8 years ago

souptown commented 9 years ago

This is not an issue. Just sharing a pattern.

Description: https://github.com/souptown/react-refluxjs-single-page-state-pattern Example: http://codepen.io/anon/pen/xwPEMe

I'll copy it here:

react-refluxjs-single-page-state-pattern

This is a pattern for implementing a single state hierarchy for a page in refluxjs. It uses the refluxjs aggregate store pattern.

Store hierarchy is:

var PageStore = Reflux.createStore({
  init: function () {
    this.state = {
      header: HeaderStore.state
    };
    this.listenTo(HeaderStore, (newHeaderState) => {
      this.state.header = newHeaderState;
      this.trigger(this.state);
    });
  }
});

var HeaderStore = Reflux.createStore({
  init: function () {
    this.state = {
      user: UserStore.state
    };
    this.listenTo(UserStore, (newUserState) => {
      this.state.user = newUserState;
      this.trigger(this.state);
    });
  }
});

var UserStore = Reflux.createStore({
  listenables: UserActions,
  init: function () {
    this.state = {
      username: '',
      loggedIn: false
    };
    UserActions.fetch();
  },
  onFetchCompleted: function (user) {
    this.state.username = user.username;
    this.state.loggedIn = true;
    this.trigger(this.state);
  },
  onLogoutCompleted: function () {
    this.state.username = '';
    this.state.loggedIn = false;
    this.trigger(this.state);
  }
});

Propagating State

Component hierarchy is:

class Page extends React.Component {
  constructor (props) {
    super(props);
    this.state = PageStore.state;
    PageStore.listen(newPageState => {
      this.setState(newPageState);
    });
  }

  render () {
    return (
      <div>
        <Header {...this.state.header} />
      </div>
    );
  }
}

class Header extends React.Component {
  render () {
    return (
      <header>
        <User {...this.props.user} />
      </header>
    );
  }
}

class User extends React.Component {
  render () {
    return (
      <div>{ this.props.username }</div>
      <button 
        onClick={ () => UserActions.logout() }
        style={ { display: this.props.loggedIn ? '' : 'none'} }>Log out</button>
    );
  }
}
LongLiveCHIEF commented 8 years ago

This is great! We should work this into our upcoming "guides" with our docs. For now, I'm going to turn it into a wiki page.

devinivy commented 8 years ago

This is a nice pattern worth knowing about. I've marked it as a resource so that we may revisit it for guidance as we pull together a site. Further discussion can (and oughtta!!) take place over at the new discussion repo (https://github.com/reflux/discuss).