├── .babelrc ├── .flowconfig ├── .gitignore ├── .watchmanconfig ├── App.js ├── App.test.js ├── README.md ├── app.json ├── demo.gif ├── package-lock.json ├── package.json ├── src ├── components │ ├── Drawer.js │ └── HeaderButton.js ├── screens │ ├── Modal.js │ └── Profile.js └── tabs │ ├── Home.js │ └── Settings.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["babel-preset-expo"], 3 | "env": { 4 | "development": { 5 | "plugins": ["transform-react-jsx-source"] 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore unexpected extra "@providesModule" 9 | .*/node_modules/.*/node_modules/fbjs/.* 10 | 11 | ; Ignore duplicate module providers 12 | ; For RN Apps installed via npm, "Libraries" folder is inside 13 | ; "node_modules/react-native" but in the source repo it is in the root 14 | .*/Libraries/react-native/React.js 15 | .*/Libraries/react-native/ReactNative.js 16 | 17 | ; Additional create-react-native-app ignores 18 | 19 | ; Ignore duplicate module providers 20 | .*/node_modules/fbemitter/lib/* 21 | 22 | ; Ignore misbehaving dev-dependencies 23 | .*/node_modules/xdl/build/* 24 | .*/node_modules/reqwest/tests/* 25 | 26 | ; Ignore missing expo-sdk dependencies (temporarily) 27 | ; https://github.com/expo/expo/issues/162 28 | .*/node_modules/expo/src/* 29 | 30 | ; Ignore react-native-fbads dependency of the expo sdk 31 | .*/node_modules/react-native-fbads/* 32 | 33 | [include] 34 | 35 | [libs] 36 | node_modules/react-native/Libraries/react-native/react-native-interface.js 37 | node_modules/react-native/flow 38 | flow/ 39 | 40 | [options] 41 | module.system=haste 42 | 43 | emoji=true 44 | 45 | experimental.strict_type_args=true 46 | 47 | munge_underscores=true 48 | 49 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' 50 | 51 | suppress_type=$FlowIssue 52 | suppress_type=$FlowFixMe 53 | suppress_type=$FixMe 54 | 55 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(4[0-2]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) 56 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(4[0-2]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ 57 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy 58 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 59 | 60 | unsafe.enable_getters_and_setters=true 61 | 62 | [version] 63 | ^0.42.0 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .expo/ 3 | npm-debug.* 4 | 5 | .DS_Store 6 | .idea 7 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | DrawerNavigator, 4 | StackNavigator, 5 | TabNavigator 6 | } from 'react-navigation'; 7 | import Icon from 'react-native-vector-icons/Ionicons'; 8 | import Home from './src/tabs/Home'; 9 | import Settings from './src/tabs/Settings'; 10 | import Profile from './src/screens/Profile'; 11 | import Modal from './src/screens/Modal'; 12 | import Drawer from './src/components/Drawer'; 13 | 14 | // Stack navigation for Settings and Profile screens 15 | const SettingsTab = StackNavigator({ 16 | Settings: { 17 | screen: Settings, 18 | navigationOptions: { 19 | header: null, // Hide the header 20 | headerBackTitle: 'Back', // Title back button Back when we navigate to Profile from Settings 21 | }, 22 | }, 23 | Profile: { 24 | screen: Profile, 25 | navigationOptions: ({ navigation }) => ({ 26 | // Customize header's title with user name passed to navigate() 27 | // You can pass any props you'd like. For instance: navigate('Profile', { user: 'Tom' } 28 | title: `${navigation.state.params.user}'s Profile`, 29 | }), 30 | }, 31 | }, { 32 | headerMode: 'screen', 33 | }); 34 | 35 | // Tab navigation for Home and Settings screens 36 | const TabNavigation = TabNavigator({ 37 | Home: { 38 | screen: Home, 39 | navigationOptions: { 40 | tabBarLabel: 'Home', 41 | tabBarIcon: ({ tintColor, focused }) => 46 | }, 47 | }, 48 | Settings: { 49 | screen: SettingsTab, 50 | navigationOptions: { 51 | tabBarLabel: 'Settings', 52 | tabBarIcon: ({ tintColor, focused }) => 57 | }, 58 | }, 59 | }); 60 | 61 | // Wrap tab navigation into drawer navigation 62 | const TabsWithDrawerNavigation = DrawerNavigator({ 63 | Tabs: { 64 | screen: TabNavigation, 65 | } 66 | }, { 67 | // Register custom drawer component 68 | contentComponent: props => 69 | }); 70 | 71 | // And lastly stack together drawer with tabs and modal navigation 72 | // because we want to be able to call Modal screen from any other screen 73 | export default StackNavigator({ 74 | TabsWithDrawer: { 75 | screen: TabsWithDrawerNavigation, 76 | }, 77 | Modal: { 78 | screen: Modal 79 | }, 80 | }, { 81 | // In modal mode screen slides up from the bottom 82 | mode: 'modal', 83 | // No headers for modals. Otherwise we'd have two headers on the screen, one for stack, one for modal. 84 | headerMode: 'none', 85 | }); 86 | -------------------------------------------------------------------------------- /App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import App from './App'; 3 | 4 | import renderer from 'react-test-renderer'; 5 | 6 | it('renders without crashing', () => { 7 | const rendered = renderer.create().toJSON(); 8 | expect(rendered).toBeTruthy(); 9 | }); 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cross-Platform Navigation in React Native 2 | 3 | Learn how to set up cross-platform navigation including tab, stack and modal navigation. 4 | 5 | ## Tutorial 6 | 7 | Read the full tutorial here http://rationalappdev.com/cross-platform-navigation-in-react-native 8 | 9 | ## Demo 10 | 11 | Demo 12 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "sdkVersion": "17.0.0" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rationalappdev/react-native-navigation-tutorial/3f4e44900c39456f714100d8642c330ae882070a/demo.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-navigation-tutorial", 3 | "version": "0.1.0", 4 | "private": true, 5 | "devDependencies": { 6 | "jest-expo": "~1.0.1", 7 | "react-native-scripts": "0.0.31", 8 | "react-test-renderer": "16.0.0-alpha.6" 9 | }, 10 | "main": "./node_modules/react-native-scripts/build/bin/crna-entry.js", 11 | "scripts": { 12 | "start": "react-native-scripts start", 13 | "eject": "react-native-scripts eject", 14 | "android": "react-native-scripts android", 15 | "ios": "react-native-scripts ios", 16 | "test": "node node_modules/jest/bin/jest.js --watch" 17 | }, 18 | "jest": { 19 | "preset": "jest-expo" 20 | }, 21 | "dependencies": { 22 | "expo": "^17.0.0", 23 | "prop-types": "^15.5.10", 24 | "react": "16.0.0-alpha.6", 25 | "react-native": "^0.44.0", 26 | "react-native-vector-icons": "^4.2.0", 27 | "react-navigation": "^1.0.0-beta.11" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/components/Drawer.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { 3 | Button, 4 | StyleSheet, 5 | Text, 6 | View 7 | } from 'react-native'; 8 | 9 | export default class Drawer extends Component { 10 | 11 | render() { 12 | const { navigate } = this.props.navigation; 13 | return ( 14 | 15 | 16 | Drawer 17 | 18 |