How can I pass props to layouts used in react-router?

Viewed 4511

Assume the following Route setup:

ReactDOM.render(  
    <Provider store={store}>
        <Router history={browserHistory}>
            <Route path="/">
                <Route component={Layout} onEnter={checkIndexAuthorization(store)}>
                    <IndexRoute component={Home} />
                    <Route path="/home" component={Home} />
                </Route>

                <Route component={AuthLayout} onEnter={checkLoginAuthorization(store)}>
                    <Route path="/login" component={Login} />
                </Route>
            </Route>
        </Router>
    </Provider>,
    document.getElementById('root'),
)

As you can see, there are two main layouts, the normal Layout and the login page AuthLayout. The normal layout is used for the app proper.

Below, you can see the Layout component file:

//========================================
// IMPORTS
//========================================

import React, { PropTypes } from 'react';

//========================================
// COMPONENT
//========================================

const Layout = props => (
    <main className="app">
        <header>
            {props.sectionTitle}
        </header>

        <section>
            {props.children}
        </section>

        <footer>

        </footer>
    </main>
)

Layout.propTypes = {
    children: PropTypes.node,
    sectionTitle: PropTypes.string // <-- not being set anywhere currently
}

//========================================
// EXPORTS
//========================================

export default Layout;

Now, that layout has a title section at the top, that needs to display text based on where in the app we are.

As I'm new to React JS, I didn't want to just look up 'how to pass props from router' or similar - rather, I'm interested in what the correct way to do this might be. The 'React way', if you will. Whether that involves passing props directly from the route, or changing a global state of some kind to affect the title, or whatever the 'correct' way of handling this scenario would be.

EDIT: I should mention that I'm using React JS v. 15.6.1, and react-router v. 3.0.5.

3 Answers

I was just looking at this too - in my application I have private routes which are only available after Authentication, which I only remembered after about 5 minutes of looking at this!

If you are creating private routes in your application, do not forget to pass props to the newly created route component e.g.:

<PrivateRoute path="/path/to/route" name={'Route name'} component={RouteComponent} layout={SimpleLayout} />

And the definition for PrivateRoute:

const PrivateRoute = ({ layout: Layout, component: Component, ...rest }) => (
    <Route {...rest} render={props => {
        const newComponent = Layout ? 
             <Layout><Component {...rest} {...props} /></Layout> 
                 : 
             <Component {...props} />;

        return Auth.isUserAuthenticated() ? (
            newComponent
        ) : (
            <Redirect to={{pathname: '/login', state: { from: props.location }}} />
        )
    }}/>
);

The important part is remembering to spread to current props onto the new Component {...rest}.

Then in the actual Layout file (eg. SimpleLayout above) you can access the props via:

this.props.children.props.name

I'm sure there are still better ways of doing this, but from my experience thus far, this worked ok for me!

Related