An exquisitely crafted routing component for Redux based React Native applications.
Providing a consistent user interface for both iOS and Android.
npm install -S react-native-redux-routing
Your Application.js should looks like below:
import React from 'react'
import { Platform } from 'react-native'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import {
actions as routerActions,
Router,
Route
} from 'react-native-redux-routing'
import * as actionsA from './actions/actionsA'
import * as actionsB from './actions/actionsB'
import { SplashPage, MainPage } from './pages'
import ExtraDimensions from 'react-native-extra-dimensions-android'
export default connect(
state => ({
router: state.router,
a: state.a,
b: state.b,
}),
dispatch => ({
actions: bindActionCreators({
...routerActions,
...actionsA,
...actionsB,
}, dispatch),
})
)(class extends React.Component {
render() {
const statusBarSize = Platform.OS === 'ios' ? 20 : Platform.Version >= 23 ? ExtraDimensions.get('STATUS_BAR_HEIGHT') : 0
const config = {
renderNavigationView: () => <NavigationDrawer />,
accentColor: '#C2185B',
transparentStatusBar: true,
statusBarStyle: 'light-content',
statusBarSize // You have to specify the size of status bar manually
}
return (
<Router {...this.props} config={config} initialRoute="splash">
<Route id="splash" component={SplashPage} immersive={true} />
<Route id="main" component={MainPage} />
</Router>
)
}
})You must set the initialRoute property to get the router working.
You can set the config property to pass in your custom configurations.
You must set the id property which is unique to each route.
You must set the component property for which class should be rendered.
You can set the immersive property to true to hide the app bar (including navigation drawer).
this.props.router.drawerOpenthis.props.router.navTitlethis.props.router.datathis.props.router.routesthis.props.router.appBarSizethis.props.router.transitioning
All router-provided actions starts with an underscore in order to prevent possible conflictions.
this.props.actions._navigate('settings') // Push the "settings" route to the routes stack
this.props.actions._navigate(-1) // Pop the last route in the routes stack
this.props.actions._navigate('home', { reset: true }) // Reset the routes stack and navigate to "home" route
this.props.actions._navigate('page-1', { sceneConfig: CustomConfig }) // Changing scene with custom animation
this.props.actions._navigate('page-2', { animated: false }) // Changing scene without animation
this.props.actions._navigate('another', { replace: true }) // Replace the current scene to new scene
this.props.actions._navigate('analytics', { data: someObject }) // Move to another scene and transferring data to itthis.props.actions._setNavAction({
renderer: () => <Text>123</Text>, // Function that returns a React element
handler: () => alert('clicked'), // Function that will triggers when the rendered element was pressed
})
this.props.actions._setNavAction(null) // Reset nav actionthis.props.actions._setNavTitle('Page Title #' + 1) // Set the page title that shows on the app barthis.props.actions._openDrawer() // Open the navigation drawerthis.props.actions._closeDrawer() // Close the navigation drawerthis.props.actions._addRouteListener('unload', () => 'Are you sure?') // Attach an `onUnload` listener for the current route
this.props.actions._addRouteListener('focus', () => 'Entered scene') // Attach an `onFocus` listener for the current route
this.props.actions._addRouteListener('blur', () => 'Leaved scene') // Attach an `onBlur` listener for the current routethis.props.actions._removeRouteListener('unload', listener) // `listener` must be the same one as you added to remove
this.props.actions._removeRouteListener('focus', listener) // `listener` must be the same one as you added to remove
this.props.actions._removeRouteListener('blur', listener) // `listener` must be the same one as you added to removeThe dispatchable actions are listed below:
import { types as routerTypes } from 'react-native-redux-routing'
dispatch({
type: routerTypes.ROUTE_PUSH,
options: {
route: 'settings',
sceneConfig: CustomConfig,
}
})
dispatch({
type: routerTypes.ROUTE_POP,
options: {
sceneConfig: CustomConfig,
}
})
dispatch({
type: routerTypes.ROUTE_REPLACE,
options: {
route: 'another',
sceneConfig: CustomConfig,
}
})
dispatch({
type: routerTypes.ROUTE_RESET,
options: {
route: 'settings',
animated: false,
}
})
dispatch({
type: routerTypes.SET_NAV_ACTION,
renderer: rendererFunc,
handler: handlerFunc,
})
dispatch({
type: routerTypes.SET_NAV_TITLE,
title: 'New Title',
})
dispatch({
type: routerTypes.OPEN_DRAWER,
})
dispatch({
type: routerTypes.CLOSE_DRAWER,
})
dispatch({
type: routerTypes.ADD_BLUR_LISTENER,
listener,
})
dispatch({
type: routerTypes.REMOVE_BLUR_LISTENER,
listener,
})
dispatch({
type: routerTypes.ADD_FOCUS_LISTENER,
listener,
})
dispatch({
type: routerTypes.REMOVE_FOCUS_LISTENER,
listener,
})
dispatch({
type: routerTypes.ADD_UNLOAD_LISTENER,
listener,
})
dispatch({
type: routerTypes.REMOVE_UNLOAD_LISTENER,
listener,
})You can modify the default configuration for the router by passing config property into its properties.
The default configuration are listed below:
const defaultConfig = {
renderNavigationView: () => null,
accentColor: '#E0E0E0',
transparentStatusBar: true,
statusBarStyle: 'default',
statusBarSize: 20,
}| Property | Type | Description |
|---|---|---|
| renderNavigationView | Function | Function that returns a React element. |
| accentColor | String |
Sets the accent color of the application, must be a solid color starting with #. |
| transparentStatusBar | Boolean | Indicates the status bar should be transparent. Android only. |
| statusBarStyle | String |
Indicates the theme should be dark or light. Enum: "default", "light-content" |
| statusBarSize | Number |
Specify the size of the status bar. Obtain yourself from other modules. |
The drawer layout uses react-native-drawer-layout module, you can setup your own navigation drawer view renderer by setting renderNavigationView property in the router config object.
render() {
const config = {
statusBarStyle: 'light-content',
renderNavigationView: () => <NavigationDrawer />,
accentColor: '#00695C',
}
return (
<Router {...this.props} config={config} initialRoute="calendar">
...
</Router>
)
}The example below shows how to adding a camera button dynamically:
componentWillMount() {
this.props.actions._setNavTitle('Camera Roll')
this.props.actions._setNavAction({
renderer: () => (
<View style={{ alignItems: 'center', flexDirection: 'row' }}>
<Icon name='camera-alt' style={{ color: '#fff', fontSize: 24 }} />
</View>
),
handler: () => {
const date = new Date
alert('Today is ' + date.toString())
}
})
}class extends React.Component {
...
componentDidMount() {
this.onSceneFocusListener = () => alert('This component is now focused from route stack!')
this.onSceneBlurListener = () => alert('This component is now blurred from route stack!')
this.props.actions._addRouteListener('focus', this.onSceneFocusListener)
this.props.actions._addRouteListener('blur', this.onSceneBlurListener)
}
componentWillUnmount() {
this.props.actions._removeRouteListener('focus', this.onSceneFocusListener)
this.props.actions._removeRouteListener('blur', this.onSceneBlurListener)
// Alert message will not be shown again from now on
}
...
}class extends React.Component {
...
state = { apples: 10 }
componentDidMount() {
this.onUnloadListener = () => {
if (this.state.apples > 0) {
return 'Are you sure you want to leave your apples?'
}
// returning null will not prompt for confirmation
return null
}
this.props.actions._addRouteListener('unload', this.onUnloadListener)
}
componentWillUnmount() {
this.props.actions._removeRouteListener('unload', this.onUnloadListener)
// Unload listener has been removed
}
...
}You can theme your application easily by setting the accentColor property in the router config object.
The default value of statusBarStyle is "default" which indicates a light theme, change it to "light-content" for dark theme.
Thanks to react-native-drawer-layout and react-native-router-redux for their awesome work.



