fluxxor
fluxxor copied to clipboard
Fluxxor and React Router 1.x and ES6
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
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}>
...
Thank you, much more simply in this way
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 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.
Bump
Probably worth mentioning that this example no longer works: https://github.com/BinaryMuse/fluxxor/blob/master/examples/react-router/app/app.jsx.
I'm trying to decide between using this and https://github.com/rackt/redux-simple-router.
Can you advise?