remix-run / react-router

Declarative routing for React
https://reactrouter.com
MIT License
53.03k stars 10.31k forks source link

What's the best way to pass props to the parent route? #546

Closed hai-cea closed 9 years ago

hai-cea commented 9 years ago

Here's what I did in 0.10.x

<Route name="root" path="/" handler={Master}>
  <Route name="home" handler={Home} />
  <Route name="get-started" handler={GetStarted} pageTitle="Get Started" />
</Route>

In the above example, pageTitle would get passed into the {Master} component when the child route matches. How can I accomplish the same thing in v0.11.x ?

ryanflorence commented 9 years ago

Have you consulted the upgrade guide? :)

https://github.com/rackt/react-router/blob/master/UPGRADE_GUIDE.md#route-props-passed-to-handlers

hai-cea commented 9 years ago

Yes I did actually :)

The examples show how to pass variables to the handler on the current route...but how do I pass variables to the handler on the parent route? Maybe I'm just not understanding...

ryanflorence commented 9 years ago

The examples don't have a "current route". I'm not understanding the question.

ryanflorence commented 9 years ago

I'm also unclear about what you mean by "parent route" because in your code at the top of this issue you don't have any custom props on the root (parent?) route.

ryanflorence commented 9 years ago

I reread the question, just move the "page title" to the GetStarted handler and access it there to send it up to Master, however you did it before.

var GetStarted = React.createClass({
  pageTitle: 'Get Started',

  componentDidMount: function () {
    // v0.10
    var title = this.props.pageTitle;

    // v0.11
    var title = this.pageTitle;
  }
});
hai-cea commented 9 years ago

In v0.10.x, the pageTitle would be accessible from the Master handler. For example:

<Route name="root" path="/" handler={Master}>
  <Route name="home" handler={Home} />
  <Route name="get-started" handler={GetStarted} pageTitle="Get Started" />
  <Route name="css-framework" handler={CssFramework} pageTitle="Css Framework" />
  <Route name="components" handler={Components} pageTitle="Components" />
</Route>

Edit: I was doing this.props.activeRouteHandler().props.pageTitle inside master to access pageTitle. Is there a way to do the same thing with RouteHandler?

Thanks!

tcoopman commented 9 years ago

I have a similar question that I don't see immediately how to solve this with 0.11:

<Route name="root" path="/" handler={App}>
  <Route name="foo" handler={Foo} sidebar={FooSidebar} />
  <Route name="bar" handler={Bar} sidebar={BarSidebar} />
</Route>

// App

var App = React:createClass({
  render: function() {
     // How do I get the sidebar?
    var Sidebar = ?????
    return (
      <div>
         <Sidebar />
        <RouteHandler />
     </div>
    );
  }
});

I think I might make this work with the close over technique but it's a uglier than in 0.10, so if there is better workaround, I would love to hear it.

// with close over technique
<Route name="root" path="/" handler={App}>
  <Route name="foo" handler={make(Foo, FooSidebar)} />
  <Route name="bar" handler={make(Bar, BarSidebar)} />
</Route>

function make(Main, Sidebar) {
  return React.createClass({
    render: function() {
       return (
         <div>
           <Sidebar />
           <Main />
         </div>
       );
     }
  })
}

var App = React:createClass({
  render: function() {
    return <RouteHandler />;
  }
});

@hai-cea In this way, your pageTitle is also accessible.

hai-cea commented 9 years ago

Thanks @tcoopman

I ended up changing my code to remove this requirement.

So in my example, in the {Home} handler, I check which route is active to set the pageTitle.

var pageTitle = 
      this.isActive('get-started') ? 'Get Started' :
      this.isActive('css-framework') ? 'Css Framework' :
      this.isActive('components') ? 'Components' : '';