I have a route structure like this:
<Route path="/master" component={MasterPageLayout}>
<IndexRoute path="/master/products" component={ProductsPage}/>
<Route path="/master/customer/:id" component={CustomerDetailsPage}/>
<Route path="/master/product/:id" component={ProductDetailsPage}/>
<Route path="/master/price-table" component={PriceTablePage} />
</Route>
<Route path="/poc" component={DistribuitorPageLayout}>
<IndexRoute path="/poc/inventory" component={InventoryPage}/>
</Route>
Inside the MasterPageLayout
I have my header and my sidemenu (common to all the nested routes above him), the props.children
is rendered inside those menus structures, but my header has a specific text for each route. How can I pass the text (and maybe some other data) from the child to the father?
Passing data back up the tree is usually handled with callbacks. As you only need to get the value once I'd recommend using one of the mounting lifecycle methods to call the callback.
As you've tagged react-redux
, I'll give examples for both a React and Redux. I don't believe the basic react example is actually suitable for your situation, as you are rendering props.children
which makes passing the callback down more difficult, but I'll leave it in the answer in case it's useful to someone else. The redux example should be applicable to your problem.
Basic React
You can pass a callback to the child that sets a value in the components state to use when rendering
class Child extends React.Component {
componentWillMount() {
this.props.setText("for example")
}
render() {
return (
<div>whatever</div>
)
}
}
class Parent extends React.Component {
render() {
return (
<div>
<Child setText={(text) => this.setState({text})} />
{this.state.text}
</div>
)
}
}
React/Redux
You could dispatch an action to set the text when the child is mounted that sets a value in the store to render in the parent, e.g.
class ChildView extends React.Component {
componentWillMount() {
this.props.setText("for example")
}
render() {
return (
<div>whatever</div>
)
}
}
const mapDispatchToProps = (dispatch) => {
return {
setText: (text) => dispatch(setParentText(text))
}
}
const Child = connect(null, mapDispatchToProps)(ChildView)
const ParentView = ({ text }) => {
return (
<div>
<Child />
{text}
</div>
)
}
const mapStateToProps = (state) => {
return {
text: state.parent.text
}
}
const Parent = connect(mapStateToProps)(ParentView)
I wont worry showing the action creator and the reducer/store setup. If you're using redux you should be able to figure that bit out.
This approach will also work if Parent
doesn't directly render Child
, whether it is through props.children
or extra layers are introduced. In fact, Parent
doesn't event need to be an ancestor of Child
at all for this approach to work, as long as both are rendered on the same page.