{"action":"created","issue":{"url":"https://api.github.com/repos/rackt/react-router/issues/1215","labels_url":"https://api.github.com/repos/rackt/react-router/issues/1215/labels{/name}","comments_url":"https://api.github.com/repos/rackt/react-router/issues/1215/comments","events_url":"https://api.github.com/repos/rackt/react-router/issues/1215/events","html_url":"https://github.com/rackt/react-router/pull/1215","id":78764212,"number":1215,"title":"[1.0] Add ability to provide a top level `render` method","user":{"login":"cpojer","id":13352,"avatar_url":"https://avatars.githubusercontent.com/u/13352?v=3","gravatar_id":"","url":"https://api.github.com/users/cpojer","html_url":"https://github.com/cpojer","followers_url":"https://api.github.com/users/cpojer/followers","following_url":"https://api.github.com/users/cpojer/following{/other_user}","gists_url":"https://api.github.com/users/cpojer/gists{/gist_id}","starred_url":"https://api.github.com/users/cpojer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cpojer/subscriptions","organizations_url":"https://api.github.com/users/cpojer/orgs","repos_url":"https://api.github.com/users/cpojer/repos","events_url":"https://api.github.com/users/cpojer/events{/privacy}","received_events_url":"https://api.github.com/users/cpojer/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":6,"created_at":"2015-05-21T00:49:37Z","updated_at":"2015-05-21T02:26:40Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/rackt/react-router/pulls/1215","html_url":"https://github.com/rackt/react-router/pull/1215","diff_url":"https://github.com/rackt/react-router/pull/1215.diff","patch_url":"https://github.com/rackt/react-router/pull/1215.patch"},"body":"This allows to inject a custom \"route handler\" (hah!). This is a useful hook to render something different from react-router's default call to `React.createElement`. This method will be called for every component on every step of the route tree and it can conditionally return a `ReactElement`. This is useful when building an application with Relay.\r\n\r\nActual Code Example:\r\n```js\r\nfunction render(component, {params, route}) {\r\n  var {name, queries, component} = route;\r\n  if (name && queries && Relay.isContainer(component)) {\r\n    return (\r\n      <RelayRootContainer\r\n        Component={component}\r\n        route={{name, params, queries}}\r\n      />\r\n    );\r\n  }\r\n}\r\n\r\nvar routes = (\r\n  <Route component={Root} render={render}>\r\n    <Route …>\r\n      <Route name=\"app\" component={App} queries={{…}} />\r\n      <Route name=\"profile\" component={Profile} queries={{…}} />\r\n      <Route name=\"events\" component={Events} queries={{…}} />\r\n    </Route>\r\n  </Route>\r\n);\r\n```\r\n\r\nThe application code is not affected by this; components will just receive `this.props.children`.\r\n\r\nIt is possible that such a render function might be useful on more steps than just the top level. In this case I would consider changing my code to walk up the matched route tree and select the first render method that is defined. If we do this, we might also want to consider walking up the matched route tree and calling all render methods (closest ones first) until one of them renders to an element."},"comment":{"url":"https://api.github.com/repos/rackt/react-router/issues/comments/104104649","html_url":"https://github.com/rackt/react-router/pull/1215#issuecomment-104104649","issue_url":"https://api.github.com/repos/rackt/react-router/issues/1215","id":104104649,"user":{"login":"cpojer","id":13352,"avatar_url":"https://avatars.githubusercontent.com/u/13352?v=3","gravatar_id":"","url":"https://api.github.com/users/cpojer","html_url":"https://github.com/cpojer","followers_url":"https://api.github.com/users/cpojer/followers","following_url":"https://api.github.com/users/cpojer/following{/other_user}","gists_url":"https://api.github.com/users/cpojer/gists{/gist_id}","starred_url":"https://api.github.com/users/cpojer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cpojer/subscriptions","organizations_url":"https://api.github.com/users/cpojer/orgs","repos_url":"https://api.github.com/users/cpojer/repos","events_url":"https://api.github.com/users/cpojer/events{/privacy}","received_events_url":"https://api.github.com/users/cpojer/received_events","type":"User","site_admin":false},"created_at":"2015-05-21T02:26:40Z","updated_at":"2015-05-21T02:26:40Z","body":"I've updated the example to include more than one route on the same level. Yes, what you are saying works but it is really inconvenient. It means that the boilerplate code from the `render` function above needs to be written out manually for every component.\r\n\r\nRelay uses a `RelayRootContainer` as an anchor point for a Relay app or part of a Relay app. A `RelayRootContainer` takes a component and a query config (a route with `{name, params, queries}`).\r\n\r\nSo without this pull request, the App component would look something like this:\r\n```js \r\nApp.render = () => {\r\n  return (\r\n    <RelayRootContainer\r\n      Component={AppContainer}\r\n      route={{name, params, queries}}\r\n    />\r\n  );\r\n};\r\n```\r\n\r\nbut then `Profile.render` and `Events.render` would look identical except for the component name. This is clearly not optimal as you might have 100 routes. Even `App.render = createRelayRendererFor(App)` is inconvenient as it requires the developer to type out this level of indirection manually every time. It also makes it more work to convert existing views to Relay one-by-one.\r\n\r\nNow another solution could be something like this:\r\n\r\n```js\r\n<Route name=\"app\" component={RootContainerWrapper} relayComponent={App} queries={{…}} />\r\n<Route name=\"profile\" component={RootContainerWrapper} relayComponent={Profile} queries={{…}} />\r\n```\r\n\r\nbut I think this is worse. It means that all the async loading logic you guys built won't work the same way. If you look at this example closely it is actually quite similar to the solution in this pull request. Except with my pull request (and the suggestion I posted above about picking the closest render) we could retain `component` for the actual component (a `RelayContainer`) and we can use `render` on the closest level where we automatically want to wrap components with a `RelayRootContainer`. In the app I'm currently using this with it works really well."}}