react-native-autopilot
Version:
Automatically push and pop navigator routes/scenes/screens if the navigator props was changed.
102 lines (88 loc) • 3.45 kB
JavaScript
import React, { Component } from 'react';
import { InteractionManager } from 'react-native';
import ExNavigator from '@exponent/react-native-navigator';
import applyNavigatorChanges from './applyNavigatorChanges';
import NavigatorWrapper from './NavigatorWrapper';
export default class ExNavigatorAutopilot extends Component {
static Styles = ExNavigator.Styles;
constructor(props) {
super(props);
// initialRouteStack
this.originRouteStack = props.routes && props.routes.length ? props.routes : [null];
this.mappedRouteStack = this.originRouteStack.map(props.routeMapping);
}
componentDidMount() {
const navigator = this.refs.navigator;
const context = navigator.navigationContext;
this.didFocusListener = context.addListener('didfocus', (event) => {
const mappedRoute = event.data.route;
InteractionManager.runAfterInteractions(() => {
this.onFocus(mappedRoute);
});
});
}
componentWillReceiveProps(nextProps) {
if (!nextProps.routeMapping) {
throw new Error('ExNavigatorAutopilot: routeMapping prop is required!');
}
const compareRoute = nextProps.compareRoute || ((routeA, routeB) => routeA === routeB);
const prevRouteStack = this.originRouteStack;
this.originRouteStack = nextProps.routes && nextProps.routes.length ? nextProps.routes : [null];
this.mappedRouteStack = this.originRouteStack.map((route, index) => {
if (compareRoute(prevRouteStack[index], route) && this.mappedRouteStack[index]) {
return this.mappedRouteStack[index];
}
return nextProps.routeMapping(route);
});
if (this.refs.navigator) {
const navigator = new NavigatorWrapper(this.refs.navigator);
applyNavigatorChanges(navigator.getCurrentRoutes(), this.mappedRouteStack, navigator);
}
}
componentWillUnmount() {
if (this.didFocusListener) {
this.didFocusListener.remove();
this.didFocusListener = null;
}
}
onFocus(mappedRoute) {
const index = this.mappedRouteStack.indexOf(mappedRoute);
if (index !== -1 && index + 1 !== this.originRouteStack.length) {
const newRouteStack = this.originRouteStack.slice(0, index + 1);
if (this.props.persistRoutes) {
this.props.persistRoutes(newRouteStack);
}
}
}
render() {
return (
<ExNavigator
ref="navigator"
initialRouteStack={this.mappedRouteStack}
showNavigationBar={this.props.showNavigationBar}
navigationBarStyle={this.props.navigationBarStyle}
titleStyle={this.props.titleStyle}
barButtonTextStyle={this.props.barButtonTextStyle}
barButtonIconStyle={this.props.barButtonIconStyle}
renderNavigationBar={this.props.renderNavigationBar}
renderBackButton={this.props.renderBackButton}
sceneStyle={this.props.sceneStyle}
style={this.props.style}
/>
);
}
}
ExNavigatorAutopilot.propTypes = {
showNavigationBar: React.PropTypes.func,
style: React.PropTypes.object,
navigationBarStyle: React.PropTypes.object,
titleStyle: React.PropTypes.object,
barButtonTextStyle: React.PropTypes.object,
barButtonIconStyle: React.PropTypes.object,
sceneStyle: React.PropTypes.object,
renderNavigationBar: React.PropTypes.func,
renderBackButton: React.PropTypes.func,
persistRoutes: React.PropTypes.func,
routes: React.PropTypes.array,
routeMapping: React.PropTypes.func.isRequired,
};