{"id":4381,"url":"https://github.com/expo/ex-navigator","last_synced_at":"2025-08-04T01:32:06.497Z","repository":{"id":34458799,"uuid":"38394701","full_name":"expo/ex-navigator","owner":"expo","description":"Route-centric navigation built on top of React Native's Navigator","archived":true,"fork":false,"pushed_at":"2018-02-17T05:18:34.000Z","size":76,"stargazers_count":522,"open_issues_count":21,"forks_count":68,"subscribers_count":41,"default_branch":"master","last_synced_at":"2025-07-28T21:19:30.704Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/expo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-01T20:58:27.000Z","updated_at":"2024-12-18T19:26:31.000Z","dependencies_parsed_at":"2022-09-07T10:12:08.283Z","dependency_job_id":null,"html_url":"https://github.com/expo/ex-navigator","commit_stats":null,"previous_names":["exponentjs/ex-navigator"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/expo/ex-navigator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/expo%2Fex-navigator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/expo%2Fex-navigator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/expo%2Fex-navigator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/expo%2Fex-navigator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/expo","download_url":"https://codeload.github.com/expo/ex-navigator/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/expo%2Fex-navigator/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268636317,"owners_count":24282075,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-03T02:00:12.545Z","response_time":2577,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-01-05T20:17:10.149Z","updated_at":"2025-08-04T01:32:06.217Z","avatar_url":"https://github.com/expo.png","language":"JavaScript","funding_links":[],"categories":["Components","JavaScript"],"sub_categories":["Navigation"],"readme":"# ExNavigator\n\n\u003e **Deprecation Warning** There are a few bugs in ex-navigator that\nrequire mutation of the state for the state to pass through the\nNavigator [[Issue\n110](https://github.com/expo/ex-navigator/issues/110)]. ~It's\nhighly recommended to use the new\n[ex-navigation](https://github.com/expo/ex-navigation) instead as\nit's a powered by React Native's \"NavigationExperimental\".~ It's\nrecommend to use\n[react-navigation](https://github.com/react-community/react-navigation)\ninstead.\n\nExNavigator is a scene navigator that is centered around routes and is built on top of React Native's Navigator. You define ExRoutes, which are plain JavaScript objects with functions to render the scene for the route and the components to display in the nav bar.\n\nThe API is in ExRoute.js and ExRouteRenderer.js.\n\nOtherwise ExNavigator is very similar to Navigator.\n\n## Why?\n[This post](https://medium.com/the-exponent-log/routing-and-navigation-in-react-native-6b27bee39603#.13j2waolq) explains the ideas that are in ExNavigator and how we use it so you can assess whether it is useful for your project, too.\n\n## Installation\n\n```\nnpm install @expo/react-native-navigator --save\n```\n\nExNavigator is compatible with React Native 0.16 and newer.\n\n## Example projects\nGithub user [Thorenandresen](https://github.com/Thorbenandresen) has two very simple bare bones projects showing ExNavigator in use:\n* [ExNavigatorExample](https://github.com/Thorbenandresen/ExNavigatorExample)\n* [ExNavigatorExampleModal](https://github.com/Thorbenandresen/ExNavigatorExampleModal)\n\n\n## Usage\n\nExNavigator's component API looks very similar to Navigator's. You specify a `routeStack` and/or `initialRoute`, along with some styles. ExNavigator will render the navigation bar for you and accepts some props to style its contents. See `ExNavigator.propTypes` for the list of accepted props.\n\n**You must use JavaScript's `import` keyword to import ExNavigator. Do not use `require()`.**\n\n```js\nimport ExNavigator from '@expo/react-native-navigator';\n\nclass Example extends React.Component {\n  render() {\n    return (\n      \u003cExNavigator\n        initialRoute={YourRouter.getHomeRoute()}\n        style={{ flex: 1 }}\n        sceneStyle={{ paddingTop: 64 }}\n      /\u003e\n    );\n  }\n}\n```\n\n### Routing\n\nThe main difference between ExNavigator and Navigator is what the route objects look like. With ExNavigator, you define what each scene looks like, what its navigation bar's contents should be, and what to do when the scene gains or loses focus. A common pattern is to define a router where you create routes:\n\n```js\n\nlet YourRouter = {\n  getHomeRoute() {\n    return {\n      // Return a React component class for the scene. It receives a prop\n      // called `navigator` that you can use to push on more routes.\n      getSceneClass() {\n        return require('./HomeScene');\n      },\n\n      // When this scene receives focus, you can run some code. We're just\n      // proxying the `didfocus` event that Navigator emits, so refer to\n      // Navigator's source code for the semantics.\n      onDidFocus(event) {\n        console.log('Home Scene received focus.');\n      },\n\n      // Return a string to display in the title section of the navigation bar.\n      // This route's title is displayed next to the back button when you push\n      // a new route on top of this one.\n      getTitle() {\n        return 'Home';\n      },\n    };\n  },\n\n\n  getProfileRoute(profile) {\n    return {\n      // You can also render a scene yourself when you need more control over\n      // the props of the scene component\n      renderScene(navigator) {\n        let ProfileScene = require('./ProfileScene');\n        return \u003cProfileScene navigator={navigator} profile={profile} /\u003e;\n      },\n\n      // There are onWillBlur and onDidBlur events when the scene loses focus.\n      // These events occur when another scene will focus or did focus,\n      // respectively. The difference between \"will\" and \"did\" is the start and\n      // end of the scene transition.\n      onDidBlur(event) {\n        console.log(`Profile Scene for ${profile} lost focus.`);\n      },\n\n      // You can render arbitrary views for the title component. Note that you\n      // also need to implement getTitle if you want the title of this route to\n      // show up in the back button to it.\n      renderTitle() {\n        return (\n          \u003cView style={{ flexDirection: 'row' }}\u003e\n            \u003cImage source={profile.photoUrl} style={styles.titlePhoto} /\u003e\n            \u003cText style={styles.titleName}\u003e{profile.name}\u003c/Text\u003e\n          \u003c/View\u003e\n        );\n      },\n\n      getTitle() {\n        return profile.name;\n      },\n\n      // Render the view to display on the right side of the navigation bar. It\n      // is typically a button but doesn't have to be.\n      renderRightButton() {\n        return (\n          \u003cButton onPress={() =\u003e { console.log('Tapped right button'); }}\u003e\n            Log\n          \u003c/Button\u003e\n        );\n      },\n    };\n  },\n};\n```\n\n### Navigating\n\nTo navigate to a new scene, you use an API very similar to Navigator's. Create a route object—perhaps with the help of your router—and give it to the ExNavigator:\n\n```js\nclass HomeScene extends React.Component {\n  render() {\n    return (\n      \u003cView style={{ justifyContent: 'center' }}\u003e\n        \u003cButton onPress={() =\u003e {\n          // Get a route object from the router\n          let profile = {\n            name: 'Alex',\n            photoUrl: 'https://images.example.com/alex.jpeg',\n          };\n          let route = YourRouter.getProfileRoute(profile);\n\n          // `navigator` is passed into your scene component when you have\n          // implemented getSceneClass in your route\n          this.props.navigator.push(route);\n        }}\u003e\n          Navigate to a profile\n        \u003c/Button\u003e\n      \u003c/View\u003e\n    );\n  }\n}\n```\n\n### iOS Scene Transition Shadow\n\nThe default scene config, `FloatFromRight`, has the ability to display a shadow just like it does natively on iOS. However, you need to define your own shadow. Add the following styles in the `sceneStyle` property on your `ExNavigator` component:\n\n```\nsceneStyle={{\n  overflow: 'visible',\n  shadowColor: '#000',\n  shadowOpacity: 0.5,\n  shadowRadius: 6\n}}\n```\n\n### Flux-based navigation\n\nYou can use the ExNavigator routing framework using Actions to change the route instead of passing around a navigator. [react-native-router-flux](https://github.com/aksonov/react-native-router-flux) is built on top of ExNavigator.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexpo%2Fex-navigator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fexpo%2Fex-navigator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexpo%2Fex-navigator/lists"}