Reputation: 137
I'm using react-router 1.0 and react-redux on an app, and I'm wondering what strategy is best to pass props to children on larger apps. Here's a basic situation:
Let's say I have a route /admin/users/edit/:id
with the following structure on its components:
Routes:
<Router>
<Route path="admin" component={Admin}>
<Route path="users" component={Users}>
<Route path="edit/:id" component={Edit}/>
</Route>
</Route>
</Router>
Admin:
class Admin extends React.Component {
render() {
return (
{this.props.children}
)
}
}
Users:
class User extends React.Component {
edit = (id, params) => {
const { dispatch } this.props;
dispatch(edit(id, params));
}
other functions (add, remove) ...
render() {
return (
{this.props.children}
)
}
}
function mapStateToProps(state) {
const { users } = state;
return { users };
}
export default connect(mapStateToProps)(User);
Edit:
class Edit extends React.Component {
submit () => {
const { id } = this.props.params;
const { firstName } = this.refs;
this.props.edit(id, {firstName: firstName.value});
}
render() {
const { id } = this.props.params;
const user = this.props.users[id];
return (
<form>
<input ref='firstName' defaultValue={user.firstName}/>
<button onClick={this.submit}>Submit</button>
</form>
)
}
}
How would I pass the users & edit function props down to the children?
I know about React.cloneElement()
(as in https://github.com/rackt/react-router/tree/master/examples/passing-props-to-children), but if I have multiple routes like /users/add
, /users/remove/:id
, etc, I would be passing and exposing all the functions (edit, add, remove...) to all children. That solution doesn't seem to work very well when you have more than one children.
I would like to keep my children as dumb as possible, and use this same structure across the application (/images/add
, /images/remove/:id
, etc).
Any suggestions?
Upvotes: 1
Views: 2042
Reputation: 8276
You have a few options:
Use React.cloneElement()
, that's something you are already aware of. I wouldn't use it for deeply nested Components though.
Use createElement()
:
<Router createElement={createElement} />
// default behavior
function createElement(Component, props) {
// make sure you pass all the props in!
return <Component {...props}/>
}
// maybe you're using something like Relay
function createElement(Component, props) {
// make sure you pass all the props in!
return <RelayContainer Component={Component} routerProps={props}/>
}
Check more on that in the React Router docs.
Note:
Context is an advanced and experimental feature. The API is likely to change in future releases.
See how to use it in the React docs.
There is also the whole thread about it in the react-router#1531.
Upvotes: 1