Nader Dabit
Teaching and building apps using React and React Native
Nader Dabit
Ships with React Native
From the Community
Current State of Native Implementations
NavigatorIOS
PROS
Current State of Native Implementations
NavigatorIOS
CONS
NavigatorIOS
Creating an instance of NavigatorIOS
import {
...
NavigatorIOS
} from 'react-native'
1. Import NavigatorIOS from React Native
2. Create or import an initial route
import Home from '../pathtohome'
3. Return the Navigator in render
render () {
return (
<NavigatorIOS
initialRoute={{
component: Home,
title: 'Home'
}} />
)
}
NavigatorIOS
Pushing and popping to the route stack
this.props.navigator.push({
component: About,
title: 'About'
})
this.props.navigator.pop()
2. Popping to a previous route (go back)
1. Pushing to a new route
NavigatorIOS
Pushing and popping to the route stack
this.props.navigator.push({
component: About,
title: 'About',
passProps: {
name: 'React Camp',
city: 'New York'
}
})
Passing properties
Current State of Native Implementations
Navigator
PROS
Current State of Native Implementations
Navigator
CONS
Navigator
Creating an instance of Navigator
import {
...
Navigator
} from 'react-native'
1. Import Navigator from React Native
2. Create or import an initial route
import Home from '../pathtohome'
3. Create renderScene method
renderScene (route, navigator) {
return <route.component
navigator={navigator}
{...route.passProps} />
}
Navigator
Return instance of Navigator:
<Navigator
renderScene={this.renderScene.bind(this)}
initialRoute={{
component: Home
}} />
Pushing and popping to the route stack:
this.props.navigator.push({
component: About
})
this.props.navigator.pop()
2. Popping to a previous route (go back)
1. Pushing to a new route
Navigator
<Navigator
configureScene={this.configureScene.bind(this)}
renderScene={this.renderScene.bind(this)}
initialRoute={{
component: Home
}} />
configureScene (route) {
if (route.type === 'modal') {
return Navigator.SceneConfigs.FloatFromBottom
}
return Navigator.SceneConfigs.FloatFromRight
}
1. Create configureScene method (available options)
2. Attach it to the navigator
this.props.navigator.push({
...
type: 'modal'
})
3. Pass type of modal when we want a modal
Current State of Native Implementations
Navigator Experimental
Navigator Experimental
Creating an instance of Navigator Experimental
Navigator Experimental
Creating an instance of Navigator Experimental
import React from 'react'
import { AppRegistry } from 'react-native'
import configureStore from './app/store/configureStore'
const store = configureStore()
import NavigationRootContainer from './app/containers/navRootContainer'
import { Provider } from 'react-redux'
const App = () => (
<Provider store={store}>
<NavigationRootContainer />
</Provider>
)
AppRegistry.registerComponent('RNComprehensiveNavigation', () => App)
Entrypoint (index.ios.js / index.android.js)
Navigator Experimental
Creating an instance of Navigator Experimental
import { POP_ROUTE, PUSH_ROUTE } from '../constants/ActionTypes'
export function push (route) {
return {
type: PUSH_ROUTE,
route
}
}
export function pop () {
return {
type: POP_ROUTE
}
}
actions/actions.js
Navigator Experimental
Creating an instance of Navigator Experimental
import { PUSH_ROUTE, POP_ROUTE } from '../constants/ActionTypes'
const initialState = {
index: 0,
key: 'root',
routes: [{ key: 'home', title: 'Home' }]
}
export default (state = initialState, action) => {
switch (action.type) {
case PUSH_ROUTE:
return {
...state,
routes: [
...state.routes,
action.route
],
index: state.index + 1
}
case POP_ROUTE:
return state.index > 0 ? {
...state,
routes: state.routes.slice(0, state.routes.length - 1),
index: state.index - 1
} : state
default:
return state
}
}
reducers/navReducer.js
Navigator Experimental
Creating an instance of Navigator Experimental
import { connect } from 'react-redux'
import { push, pop } from '../actions/navActions'
import NavigationRoot from '../components/NavRoot'
function mapStateToProps (state) {
return {
navigation: state.navReducer
}
}
function mapDispatchToProps (dispatch) {
return {
pushRoute: (route) => dispatch(push(route)),
popRoute: () => dispatch(pop())
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(NavigationRoot)
navRootContainer.js
Navigator Experimental
Creating an instance of Navigator Experimental
import React, { Component } from 'react'
import Home from './Home'
import About from './About'
import {
NavigationExperimental
} from 'react-native'
const {
CardStack: NavigationCardStack
} = NavigationExperimental
containers/navigationRoot.js
Navigator Experimental
_renderScene (props) {
const { route } = props.scene
if (route.key === 'home') {
return <Home _handleNavigate={this._onNavigate.bind(this)} />
}
if (route.key === 'about') {
return <About _goBack={this.props.popRoute.bind(this)} />
}
}
containers/navRoot.js - renderScene
{
key: 'home',
title: 'Home'
}
props.scene.route
routes: [{
key: 'home',
title: 'Home'
}]
reducer initial route array
Navigator Experimental
_onNavigate (action) {
switch (action.type) {
case 'push':
this.props.pushRoute(action.route)
return true
case 'pop':
this.props.popRoute()
return true
default:
return false
}
}
containers/navRoot.js - renderScene
Navigator Experimental
render () {
return (
<NavigationCardStack
navigationState={this.props.navigation}
onNavigate={this._onNavigate.bind(this)}
renderScene={this._renderScene.bind(this)} />
)
}
rendering the NavigationCardStack component
React Native Navigation
Community / Open Source implementations
React Native Navigation
Community / Open Source implementations
import { Navigation } from 'react-native-navigation'
import { registerScreens } from './screens'
registerScreens()
Navigation.startTabBasedApp({
tabs: [
{
label: 'One',
screen: 'FirstTabScreen',
icon: require('./img/one.png'),
selectedIcon: require('./img/one_selected.png'),
title: 'Scrseen One'
},
{
label: 'Two',
screen: 'SecondTabScreen',
icon: require('./img/two.png'),
selectedIcon: require('./img/two_selected.png'),
title: 'Screen Two'
}
]
})
npm i react-native-navigation --save
React Native Navigation
import { Navigation } from 'react-native-navigation';
import FirstTabScreen from './FirstTabScreen';
import SecondTabScreen from './SecondTabScreen';
import PushedScreen from './PushedScreen';
export function registerScreens() {
Navigation.registerComponent('FirstTabScreen', () => FirstTabScreen);
Navigation.registerComponent('SecondTabScreen', () => SecondTabScreen);
Navigation.registerComponent('PushedScreen', () => PushedScreen);
}
screens.js
navigate () {
this.props.navigator.push({
screen: 'PushedScreen'
})
}
push route
this.props.navigator.pop()
pop route
Community / Open Source implementations
React Native Simple Router
Community / Open Source implementations
React Native Simple Router
npm install react-native-simple-router --save
import Router from 'react-native-simple-router'
import Home from './Home'
const firstRoute = {
name: 'Home!',
component: Home
}
class RNComprehensiveNavigation extends Component {
render() {
return (
<Router
firstRoute={firstRoute}
headerStyle={styles.header} />
)
}
}
Community / Open Source implementations
React Native Simple Router
this.props.toRoute({
name: 'About',
component: About,
passProps: {
title: 'Hello From React Camp'
}
})
this.props.toBack()
Basic navigator methods
Community / Open Source implementations
React Native Router Flux
Community / Open Source implementations
React Native Router Flux
npm i react-native-router-flux --save
import React from 'react'
import { AppRegistry } from 'react-native'
import {Scene, Router} from 'react-native-router-flux'
import Home from './Home'
import About from './About'
import More from './More'
class RNComprehensiveNavigation extends React.Component {
render() {
return <Router>
<Scene key='root'>
<Scene key='home' component={Home} title='Home' />
<Scene key='about' component={About} title='About'/>
<Scene key='more' component={More} title='More'/>
</Scene>
</Router>
}
}
React Native Router Flux
import { Actions } from 'react-native-router-flux'
Actions.about()
Actions.home()
Actions.more()
Actions.pop()
// Pass Props
Actions.more({
firstName: 'Nader',
lastName: 'Dabit',
conference: 'React Camp'
})
Scenes
<Scene key='home' component={Home} title='Home' />
<Scene key='about' component={About} title='About'/>
<Scene key='more' component={More} title='More'/>
Methods
Pass all props with passProps boolean
<Scene key='home' component={Home} title='Home' passProps />
Community / Open Source implementations
ExNavigation by Exponent
ExNavigation
npm i @exponent/ex-navigation babel-preset-react-native-stage-0 --save
Router (Create app Routes)
import {
createRouter
} from '@exponent/ex-navigation';
import Home from './Home'
import About from './About'
const Router = createRouter(() => ({
home: () => Home,
about: () => About,
}));
export default Router
import Router from './Router'
import {
NavigationProvider,
StackNavigation,
} from '@exponent/ex-navigation';
const App = () => (
<NavigationProvider router={Router}>
<StackNavigation
defaultRouteConfig={{
navigationBar: {
backgroundColor: '#000',
tintColor: '#fff',
}
}}
initialRoute={Router.getRoute('home')} />
</NavigationProvider>
)
ExNavigation
StackNavigation Component
import Router from './Router'
const people = ['amy', 'matt', 'leslie']
export default class Home extends Component {
static route = {
navigationBar: {
title: 'Home',
}
}
_goToAbout = () => {
this.props.navigator.push(Router.getRoute('about', {people}));
}
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to Home
</Text>
<TouchableHighlight onPress={this._goToAbout}>
<Text>Go to About</Text>
</TouchableHighlight>
</View>
);
}
}
Home Component
ExNavigation
class SignOutButton extends Component {
render() {
return (
<TouchableOpacity onPress={() => console.log('hello')}>
<Text style={{marginRight: 15, marginTop: 12, color: 'white'}}>Sign out</Text>
</TouchableOpacity>
);
}
}
export default class About extends Component {
static route = {
navigationBar: {
title: 'About',
renderRight: () => <SignOutButton />
}
}
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to About
</Text>
{
this.props.people.map((p, i) => {
return <Text key={i}>{p}</Text>
})
}
</View>
);
}
}
About Component
ExNavigation
ExNavigation
Community / Open Source implementations
React Router Native
React Router Native
const Master = (props) => (
<View>
{props.children}
</View>
);
const routes = (
<Router history={nativeHistory} addressBar>
<StackRoute path="master" component={Master}>
<Route path="/" component={Home} overlayComponent={HomeHeader} />
<Route path="/detail/:themeColor"
component={Detail}
overlayComponent={DetailHeader} />
</StackRoute>
</Router>
);
AppRegistry.registerComponent('YourApp', () => () => routes);
React Native Navigation - Takeaways
Comprehensive Navigation in React Native
Nader Dabit
React Native Radio
React Native in Action - Manning Publications
By Nader Dabit
React Remote Conf 2016