{"action":"created","issue":{"url":"https://api.github.com/repos/reactjs/react-router/issues/3656","repository_url":"https://api.github.com/repos/reactjs/react-router","labels_url":"https://api.github.com/repos/reactjs/react-router/issues/3656/labels{/name}","comments_url":"https://api.github.com/repos/reactjs/react-router/issues/3656/comments","events_url":"https://api.github.com/repos/reactjs/react-router/issues/3656/events","html_url":"https://github.com/reactjs/react-router/pull/3656","id":166712388,"number":3656,"title":"Feature-flagged conditional routes, externalContext proposal","user":{"login":"ivankravchenko","id":467251,"avatar_url":"https://avatars.githubusercontent.com/u/467251?v=3","gravatar_id":"","url":"https://api.github.com/users/ivankravchenko","html_url":"https://github.com/ivankravchenko","followers_url":"https://api.github.com/users/ivankravchenko/followers","following_url":"https://api.github.com/users/ivankravchenko/following{/other_user}","gists_url":"https://api.github.com/users/ivankravchenko/gists{/gist_id}","starred_url":"https://api.github.com/users/ivankravchenko/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ivankravchenko/subscriptions","organizations_url":"https://api.github.com/users/ivankravchenko/orgs","repos_url":"https://api.github.com/users/ivankravchenko/repos","events_url":"https://api.github.com/users/ivankravchenko/events{/privacy}","received_events_url":"https://api.github.com/users/ivankravchenko/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":9,"created_at":"2016-07-21T00:30:40Z","updated_at":"2016-08-22T15:42:27Z","closed_at":"2016-07-21T01:13:44Z","pull_request":{"url":"https://api.github.com/repos/reactjs/react-router/pulls/3656","html_url":"https://github.com/reactjs/react-router/pull/3656","diff_url":"https://github.com/reactjs/react-router/pull/3656.diff","patch_url":"https://github.com/reactjs/react-router/pull/3656.patch"},"body":"## Proposal\r\nAccept `externalContext` property for `<Router />` and `match({ externalContext })` and pass it along to route configuration (to `createRouteFromReactElement`, `getChildRoutes` etc).\r\n\r\n## Use case\r\nI'm trying to implement clean feature flags approach.\r\nFirst thought would be to implement it through plain JS. Example:\r\n\r\n*SomeComponent.jsx*:\r\n```jsx\r\nrender() {\r\n  return (\r\n    <div>\r\n      ...\r\n      {featureFlags.feature1 && (\r\n        ... render this if feature1 is enabled\r\n      )}\r\n      ...\r\n    </div>\r\n  );\r\n}\r\n```\r\n\r\n*routes.js*:\r\n```jsx\r\nexport default (featureFlags) => (\r\n  <Route>\r\n    <Route path=\"about\" component={...} />\r\n    {featureFlags.feature1 && (\r\n      <Route path=\"feature1\" component={...} />\r\n    )}\r\n  </Route>\r\n);\r\n```\r\n\r\nThis might be good enough, but I thought it would be nice to write clean JSX. Example:\r\n*SomeComponent.jsx*:\r\n```jsx\r\nrender() {\r\n  return (\r\n    <div>\r\n      ...\r\n      <FeatureFlag on=\"feature1\">\r\n        ... render this if feature1 is enabled\r\n      </FeatureFlag>\r\n      ...\r\n    </div>\r\n  );\r\n}\r\n```\r\n\r\n*routes.js*:\r\n```jsx\r\nexport default (\r\n  <Route>\r\n    <Route path=\"about\" component={...} />\r\n    <FeatureFlag on=\"feature1\">\r\n      <Route path=\"feature1\" component={...} />\r\n    </FeatureFlag>\r\n  </Route>\r\n);\r\n```\r\nBut Router does not \"render\" (and does not instantiate) `FeatureFlag` component. It just uses JSX as convenient method to define route configuration tree.\r\n\r\n## Implementation idea\r\nTo make last example work, I dove into React Router code and ended up with code like this:\r\n*FeatureFlag.js*:\r\n```jsx\r\nclass FeatureFlag extends React.Component {\r\n  static createRouteFromReactElement(element, parentRoute) {\r\n    if (... CONDITION ...) {\r\n      return {childRoutes: createRoutes(element.props.children)};\r\n    }\r\n    return null;\r\n  }\r\n}\r\n```\r\nThis allows to pass through child routes by certain condition.\r\nThe problem is that there is no enough information in scope of `createRouteFromReactElement` to perform `CONDITION`.\r\n\r\nIf I could provide something into router (into `<Router />` client-side and `match` server-side) and read that something in `createRouteFromReactElement`, then I get full power to implement desired feature flags approach (and so nice JSX conditional routes).\r\n\r\n## Next steps\r\nThis PR's code changes show possible way of passing along `externalContext`, which solves my use case.\r\nIn order to make this PR consistent and ready for merge, I would need to provide similar functionality to `getChildRoutes` as well (to support async routing) and write corresponding tests.\r\n\r\nBefore burning down this into PR (and depend on that in my codebase), I'd like to get maintainer's opinion on whether it's worth continuing.\r\nThanks!"},"comment":{"url":"https://api.github.com/repos/reactjs/react-router/issues/comments/241455057","html_url":"https://github.com/reactjs/react-router/pull/3656#issuecomment-241455057","issue_url":"https://api.github.com/repos/reactjs/react-router/issues/3656","id":241455057,"user":{"login":"mealeyst","id":1794777,"avatar_url":"https://avatars.githubusercontent.com/u/1794777?v=3","gravatar_id":"","url":"https://api.github.com/users/mealeyst","html_url":"https://github.com/mealeyst","followers_url":"https://api.github.com/users/mealeyst/followers","following_url":"https://api.github.com/users/mealeyst/following{/other_user}","gists_url":"https://api.github.com/users/mealeyst/gists{/gist_id}","starred_url":"https://api.github.com/users/mealeyst/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mealeyst/subscriptions","organizations_url":"https://api.github.com/users/mealeyst/orgs","repos_url":"https://api.github.com/users/mealeyst/repos","events_url":"https://api.github.com/users/mealeyst/events{/privacy}","received_events_url":"https://api.github.com/users/mealeyst/received_events","type":"User","site_admin":false},"created_at":"2016-08-22T15:42:26Z","updated_at":"2016-08-22T15:42:26Z","body":"@taion & @ivankravchenko , so I apologize for commenting on a closed PR (and I know this might not be the right platform to ask this question) but I was curious if you could point me in the direction for how you accomplished Feature Flags in React Router. I had set up something similar at first to what @ivankravchenko attempted to do and I then found this conversation. I was just curious as to what the external helper looked like."}}
{"actor":{"display_login":"mealeyst"}}