Redux is a great tool, but there are many React apps that don't need all that power. Unfortunately, when using React Router, passing the state of a stateful component to the props of stateless component without Redux is still a pain in the ass. It typically requires a series of switch...case
or if...else if
statements in a stateful component that duplicate the work of the routing system.
What I'd love to see is a this.props.route.match
property (or whatever you want to call it) that contains the complete match path of a <Route />
component. That way, a stateful component can map the complete match path to a props object that'll eventually be sent to a cloned stateless component. For an example, see the following code example.
In summary, please throw non-Redux apps a bone by passing the complete match path to a Route component.
// index.js
import React from 'react'
import { render } from 'react-dom'
import { Router, Route, browserHistory } from 'react-router'
import App from './App'
import Foo from './Foo'
import Bar from './Bar'
render(
<Router history={browserHistory}>
<Route path="/" component={App}>
<Route path="foo" component={Foo}>
<Route path="bar/:baz" component={Bar}>
</Route>
</Router>,
document.getElementById('app')
);
// App.js
import React from 'react';
const App = React.createClass({
getInitialState() {
return { foo: true, bar: false };
},
toggleFoo() {
this.setState({ foo: !this.state.foo });
},
toggleBar() {
this.setState({ bar: !this.state.bar });
},
getChildrenProps() {
const props = {
'/foo': {
foo: this.state.foo,
toggleFoo: this.toggleFoo
},
'/bar/:baz': {
bar: this.state.bar,
toggleBar: this.toggleBar,
baz: this.props.location.params.baz
}
};
// Look ma', no conditions
return props[this.props.route.match];
},
render() {
const children = React.cloneElement(
this.props.children,
getChildrenProps()
);
return <div>{children}</div>;
}
})
export default App;
// Foo.js
import React from 'react';
const Foo = React.createClass({
handleClick() {
this.props.toggleFoo();
},
render() {
return <button onClick={this.handleClick}>{this.props.foo}</div>;
}
})
export default Foo;
// Bar.js
import React from 'react';
const Bar = React.createClass({
handleClick() {
this.props.toggleBar();
},
render() {
return <button onClick={this.handleClick}>
{this.props.bar} - {this.props.baz}
</div>;
}
})
export default Bar;
Everything you need is on props.routes
.
I took the time to write out a code example in detail. I'd appreciate it if you did the same.
We don't build a complete "matched path" in routing. The set of all matched routes is on props.routes
.
Most helpful comment
I took the time to write out a code example in detail. I'd appreciate it if you did the same.