fluxxor icon indicating copy to clipboard operation
fluxxor copied to clipboard

Fluxxor and React Router 1.x and ES6

Open manuelmazzuola opened this issue 8 years ago • 7 comments

Hello, I had a lot of troubles to run together fluxxor react-router 1.x and ES6 This is my solution, hoping will help someone.

With the new react router the Handler component has gone! I've copied, pasted and modified the Root component from the baobab-react module. In this way we can pass flux prop down to the components.

function rootPass(props) {
  const {
    children,
    tree,
    ...otherProps
  } = props;

  return {...otherProps};
}

function renderChildren(children, props) {
  if (!children)
    return null;

  if (!Array.isArray(children)) {
    return React.addons.cloneWithProps(children, props);
  }
  else {
    var group = React.Children.map(children, function(child) {
      return React.addons.cloneWithProps(child, props);
    });

    return <span>{group}</span>;
  }
}

export class Root extends React.Component {
  getChildContext() {
    return {
      flux: this.props.flux
    };
  }
  render() {
    return renderChildren(this.props.children, rootPass(this.props));
  }
}

Root.propTypes = {
  flux: (t) => {if(!t.flux) return new Error('Powerzone inversion!')}
}

Root.childContextTypes = {
  flux: (t) => {if(!t.flux) return new Error('Powerzone inversion!')}
};

React.render(
  <Root flux={flux}>
    <Router>
      <Route path="/" component={Layout}>
        <IndexRoute component={Landing}/>
      </Route>
    </Router>
  </Root>
  , document.getElementById('content')
);

For the mixins I've used react-mixins

import Fluxxor from 'fluxxor'
const FluxMixin = Fluxxor.FluxMixin(React)

class Layout extends React.Component {
  render() {
    return (
      <div>{this.props.children}</div>
    )
  }
}

Mixin.onClass(Layout, FluxMixin);
export default Layout

And then the real problem was the StoreWatchMixin mixin because it is a mixin and because the bindings, so I've resolved in this way:

import Fluxxor from 'fluxxor'
const FluxMixin = Fluxxor.FluxMixin(React)
const StoreWatchMixin = Fluxxor.StoreWatchMixin

class GamesList extends React.Component {
  _componentWillMount() {
    this.getFlux().actions.loadGames()
  }

  getStateFromFlux() {
    let store = this.getFlux().store('GameStore')
    return {
      loading: store.loading,
      error: store.error,
      games: _.values(store.games)
    }
  }

  ...
}

Mixin.onClass(GamesList, FluxMixin)
Mixin.onClass(GamesList, StoreWatchMixin('GameStore'))
Mixin.onClass(GamesList, autobind(Object.keys(StoreWatchMixin)))

The autobind method is this:

function autobind(methodNames) {
  return {
    componentWillMount: function() {
      methodNames.forEach((name) => {
        this[name] = this[name].bind(this)
      })

      if(this._componentWillMount)
        this._componentWillMount()
    }
  }
}

export default autobind

manuelmazzuola avatar Sep 17 '15 13:09 manuelmazzuola

Hey, @manuelmazzuola, thanks for the info!

One additional note, with React Router 1.0 RC1, you can use the new createElement router prop to simplify getting the flux instance to your route handlers (though you still need a root component to pass context; Fluxxor should probably just come with one).

const createFluxComponent = (Component, props) => {
  return <Component {...props} flux={flux} />;
};

React.render(
  <Router createElement={createFluxElement}>
  ...

BinaryMuse avatar Sep 17 '15 15:09 BinaryMuse

Thank you, much more simply in this way

manuelmazzuola avatar Sep 17 '15 15:09 manuelmazzuola

I'm working on the same problem right now. Difficult that they choose to change the API so much but hopefully it's stable now. Any chance we could either push @manuelmazzuola 's example into the examples for future readers? One I figure my project out I'd be happy to write a version in 1.0 but I do think it makes sense to keep both examples side by side for a while as there are probably still people using pre-1.0 versions of react-router.

PendletonJones avatar Oct 20 '15 23:10 PendletonJones

@PendletonJones I'll definitely get the example in once React Router 1.0 comes out of release candidate status. In the meantime take a look at #141 if you're still having issues with this, and feel free to let me know if you continue to have problems.

BinaryMuse avatar Oct 21 '15 16:10 BinaryMuse

Bump

ajsharp avatar Dec 20 '15 00:12 ajsharp

Probably worth mentioning that this example no longer works: https://github.com/BinaryMuse/fluxxor/blob/master/examples/react-router/app/app.jsx.

ajsharp avatar Dec 20 '15 03:12 ajsharp

I'm trying to decide between using this and https://github.com/rackt/redux-simple-router.

Can you advise?

es6Test avatar Dec 31 '15 23:12 es6Test