Passing data from child route to father route

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?

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

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.

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply