[ReactNative] Remove dependencies on Navigator idStack
Summary: idStack is going away soon. This removes all references to it. Looking at the internal state of navigator will make you have a bad time. The biggest change is switching to the new component-freezing techinique in the navigation bars. This way we avoid dependence on the idStack to provide a scalar ID for each route.
This commit is contained in:
parent
c4389c006f
commit
c28d33f3a2
|
@ -33,6 +33,8 @@ var StaticContainer = require('StaticContainer.react');
|
|||
var StyleSheet = require('StyleSheet');
|
||||
var View = require('View');
|
||||
|
||||
var { Map } = require('immutable');
|
||||
|
||||
var invariant = require('invariant');
|
||||
|
||||
var Interpolators = NavigatorBreadcrumbNavigationBarStyles.Interpolators;
|
||||
|
@ -86,7 +88,6 @@ var NavigatorBreadcrumbNavigationBar = React.createClass({
|
|||
}),
|
||||
navState: React.PropTypes.shape({
|
||||
routeStack: React.PropTypes.arrayOf(React.PropTypes.object),
|
||||
idStack: React.PropTypes.arrayOf(React.PropTypes.number),
|
||||
presentedIndex: React.PropTypes.number,
|
||||
}),
|
||||
style: View.propTypes.style,
|
||||
|
@ -173,11 +174,19 @@ var NavigatorBreadcrumbNavigationBar = React.createClass({
|
|||
}
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this._descriptors = {
|
||||
crumb: new Map(),
|
||||
title: new Map(),
|
||||
right: new Map(),
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var navState = this.props.navState;
|
||||
var icons = navState && navState.routeStack.map(this._renderOrReturnBreadcrumb);
|
||||
var titles = navState.routeStack.map(this._renderOrReturnTitle);
|
||||
var buttons = navState.routeStack.map(this._renderOrReturnRightButton);
|
||||
var icons = navState && navState.routeStack.map(this._getBreadcrumb);
|
||||
var titles = navState.routeStack.map(this._getTitle);
|
||||
var buttons = navState.routeStack.map(this._getRightButton);
|
||||
return (
|
||||
<View style={[styles.breadCrumbContainer, this.props.style]}>
|
||||
{titles}
|
||||
|
@ -187,104 +196,69 @@ var NavigatorBreadcrumbNavigationBar = React.createClass({
|
|||
);
|
||||
},
|
||||
|
||||
_renderOrReturnBreadcrumb: function(route, index) {
|
||||
var uid = this.props.navState.idStack[index];
|
||||
var navBarRouteMapper = this.props.routeMapper;
|
||||
var navOps = this.props.navigator;
|
||||
var alreadyRendered = this.refs['crumbContainer' + uid];
|
||||
if (alreadyRendered) {
|
||||
// Don't bother re-calculating the children
|
||||
return (
|
||||
<StaticContainer
|
||||
ref={'crumbContainer' + uid}
|
||||
key={'crumbContainer' + uid}
|
||||
shouldUpdate={false}
|
||||
/>
|
||||
);
|
||||
_getBreadcrumb: function(route, index) {
|
||||
if (this._descriptors.crumb.has(route)) {
|
||||
return this._descriptors.crumb.get(route);
|
||||
}
|
||||
|
||||
var navBarRouteMapper = this.props.routeMapper;
|
||||
var firstStyles = initStyle(index, navStatePresentedIndex(this.props.navState));
|
||||
return (
|
||||
<StaticContainer
|
||||
ref={'crumbContainer' + uid}
|
||||
key={'crumbContainer' + uid}
|
||||
shouldUpdate={false}>
|
||||
<View ref={'crumb_' + index} style={firstStyles.Crumb}>
|
||||
<View ref={'icon_' + index} style={firstStyles.Icon}>
|
||||
{navBarRouteMapper.iconForRoute(route, navOps)}
|
||||
</View>
|
||||
<View ref={'separator_' + index} style={firstStyles.Separator}>
|
||||
{navBarRouteMapper.separatorForRoute(route, navOps)}
|
||||
</View>
|
||||
|
||||
var breadcrumbDescriptor = (
|
||||
<View ref={'crumb_' + index} style={firstStyles.Crumb}>
|
||||
<View ref={'icon_' + index} style={firstStyles.Icon}>
|
||||
{navBarRouteMapper.iconForRoute(route, this.props.navigator)}
|
||||
</View>
|
||||
</StaticContainer>
|
||||
<View ref={'separator_' + index} style={firstStyles.Separator}>
|
||||
{navBarRouteMapper.separatorForRoute(route, this.props.navigator)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
||||
this._descriptors.crumb = this._descriptors.crumb.set(route, breadcrumbDescriptor);
|
||||
return breadcrumbDescriptor;
|
||||
},
|
||||
|
||||
_renderOrReturnTitle: function(route, index) {
|
||||
var navState = this.props.navState;
|
||||
var uid = navState.idStack[index];
|
||||
var alreadyRendered = this.refs['titleContainer' + uid];
|
||||
if (alreadyRendered) {
|
||||
// Don't bother re-calculating the children
|
||||
return (
|
||||
<StaticContainer
|
||||
ref={'titleContainer' + uid}
|
||||
key={'titleContainer' + uid}
|
||||
shouldUpdate={false}
|
||||
/>
|
||||
);
|
||||
_getTitle: function(route, index) {
|
||||
if (this._descriptors.title.has(route)) {
|
||||
return this._descriptors.title.get(route);
|
||||
}
|
||||
var navBarRouteMapper = this.props.routeMapper;
|
||||
var titleContent = navBarRouteMapper.titleContentForRoute(
|
||||
navState.routeStack[index],
|
||||
|
||||
var titleContent = this.props.routeMapper.titleContentForRoute(
|
||||
this.props.navState.routeStack[index],
|
||||
this.props.navigator
|
||||
);
|
||||
var firstStyles = initStyle(index, navStatePresentedIndex(this.props.navState));
|
||||
return (
|
||||
<StaticContainer
|
||||
ref={'titleContainer' + uid}
|
||||
key={'titleContainer' + uid}
|
||||
shouldUpdate={false}>
|
||||
<View ref={'title_' + index} style={firstStyles.Title}>
|
||||
{titleContent}
|
||||
</View>
|
||||
</StaticContainer>
|
||||
|
||||
var titleDescriptor = (
|
||||
<View ref={'title_' + index} style={firstStyles.Title}>
|
||||
{titleContent}
|
||||
</View>
|
||||
);
|
||||
this._descriptors.title = this._descriptors.title.set(route, titleDescriptor);
|
||||
return titleDescriptor;
|
||||
},
|
||||
|
||||
_renderOrReturnRightButton: function(route, index) {
|
||||
var navState = this.props.navState;
|
||||
var navBarRouteMapper = this.props.routeMapper;
|
||||
var uid = navState.idStack[index];
|
||||
var alreadyRendered = this.refs['rightContainer' + uid];
|
||||
if (alreadyRendered) {
|
||||
// Don't bother re-calculating the children
|
||||
return (
|
||||
<StaticContainer
|
||||
ref={'rightContainer' + uid}
|
||||
key={'rightContainer' + uid}
|
||||
shouldUpdate={false}
|
||||
/>
|
||||
);
|
||||
_getRightButton: function(route, index) {
|
||||
if (this._descriptors.right.has(route)) {
|
||||
return this._descriptors.right.get(route);
|
||||
}
|
||||
var rightContent = navBarRouteMapper.rightContentForRoute(
|
||||
navState.routeStack[index],
|
||||
var rightContent = this.props.routeMapper.rightContentForRoute(
|
||||
this.props.navState.routeStack[index],
|
||||
this.props.navigator
|
||||
);
|
||||
if (!rightContent) {
|
||||
this._descriptors.right = this._descriptors.right.set(route, null);
|
||||
return null;
|
||||
}
|
||||
var firstStyles = initStyle(index, navStatePresentedIndex(this.props.navState));
|
||||
return (
|
||||
<StaticContainer
|
||||
ref={'rightContainer' + uid}
|
||||
key={'rightContainer' + uid}
|
||||
shouldUpdate={false}>
|
||||
<View ref={'right_' + index} style={firstStyles.RightItem}>
|
||||
{rightContent}
|
||||
</View>
|
||||
</StaticContainer>
|
||||
var rightButtonDescriptor = (
|
||||
<View ref={'right_' + index} style={firstStyles.RightItem}>
|
||||
{rightContent}
|
||||
</View>
|
||||
);
|
||||
this._descriptors.right = this._descriptors.right.set(route, rightButtonDescriptor);
|
||||
return rightButtonDescriptor;
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@ var StaticContainer = require('StaticContainer.react');
|
|||
var StyleSheet = require('StyleSheet');
|
||||
var View = require('View');
|
||||
|
||||
var { Map } = require('immutable');
|
||||
|
||||
var COMPONENT_NAMES = ['Title', 'LeftButton', 'RightButton'];
|
||||
|
||||
var navStatePresentedIndex = function(navState) {
|
||||
|
@ -53,7 +55,6 @@ var NavigatorNavigationBar = React.createClass({
|
|||
}),
|
||||
navState: React.PropTypes.shape({
|
||||
routeStack: React.PropTypes.arrayOf(React.PropTypes.object),
|
||||
idStack: React.PropTypes.arrayOf(React.PropTypes.number),
|
||||
presentedIndex: React.PropTypes.number,
|
||||
}),
|
||||
style: View.propTypes.style,
|
||||
|
@ -63,6 +64,16 @@ var NavigatorNavigationBar = React.createClass({
|
|||
Styles: NavigatorNavigationBarStyles,
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this._components = {};
|
||||
this._descriptors = {};
|
||||
|
||||
COMPONENT_NAMES.forEach(componentName => {
|
||||
this._components[componentName] = new Map();
|
||||
this._descriptors[componentName] = new Map();
|
||||
});
|
||||
},
|
||||
|
||||
_getReusableProps: function(
|
||||
/*string*/componentName,
|
||||
/*number*/index
|
||||
|
@ -104,7 +115,7 @@ var NavigatorNavigationBar = React.createClass({
|
|||
}
|
||||
|
||||
COMPONENT_NAMES.forEach(function (componentName) {
|
||||
var component = this.refs[componentName + index];
|
||||
var component = this._components[componentName].get(this.props.navState.routeStack[index]);
|
||||
var props = this._getReusableProps(componentName, index);
|
||||
if (component && interpolate[componentName](props.style, amount)) {
|
||||
component.setNativeProps(props);
|
||||
|
@ -128,7 +139,7 @@ var NavigatorNavigationBar = React.createClass({
|
|||
var navState = this.props.navState;
|
||||
var components = COMPONENT_NAMES.map(function (componentName) {
|
||||
return navState.routeStack.map(
|
||||
this._renderOrReturnComponent.bind(this, componentName)
|
||||
this._getComponent.bind(this, componentName)
|
||||
);
|
||||
}, this);
|
||||
|
||||
|
@ -139,28 +150,19 @@ var NavigatorNavigationBar = React.createClass({
|
|||
);
|
||||
},
|
||||
|
||||
_renderOrReturnComponent: function(
|
||||
_getComponent: function(
|
||||
/*string*/componentName,
|
||||
/*object*/route,
|
||||
/*number*/index
|
||||
) /*object*/ {
|
||||
var navState = this.props.navState;
|
||||
var uid = navState.idStack[index];
|
||||
var containerRef = componentName + 'Container' + uid;
|
||||
var alreadyRendered = this.refs[containerRef];
|
||||
if (alreadyRendered) {
|
||||
// Don't bother re-calculating the children
|
||||
return (
|
||||
<StaticContainer
|
||||
ref={containerRef}
|
||||
key={containerRef}
|
||||
shouldUpdate={false}
|
||||
/>
|
||||
);
|
||||
) /*?Object*/ {
|
||||
if (this._descriptors[componentName].includes(route)) {
|
||||
return this._descriptors[componentName].get(route);
|
||||
}
|
||||
|
||||
var rendered = null;
|
||||
|
||||
var content = this.props.routeMapper[componentName](
|
||||
navState.routeStack[index],
|
||||
this.props.navState.routeStack[index],
|
||||
this.props.navigator,
|
||||
index,
|
||||
this.props.navState
|
||||
|
@ -171,16 +173,18 @@ var NavigatorNavigationBar = React.createClass({
|
|||
|
||||
var initialStage = index === navStatePresentedIndex(this.props.navState) ?
|
||||
NavigatorNavigationBarStyles.Stages.Center : NavigatorNavigationBarStyles.Stages.Left;
|
||||
return (
|
||||
<StaticContainer
|
||||
ref={containerRef}
|
||||
key={containerRef}
|
||||
shouldUpdate={false}>
|
||||
<View ref={componentName + index} style={initialStage[componentName]}>
|
||||
{content}
|
||||
</View>
|
||||
</StaticContainer>
|
||||
rendered = (
|
||||
<View
|
||||
ref={(ref) => {
|
||||
this._components[componentName] = this._components[componentName].set(route, ref);
|
||||
}}
|
||||
style={initialStage[componentName]}>
|
||||
{content}
|
||||
</View>
|
||||
);
|
||||
|
||||
this._descriptors[componentName] = this._descriptors[componentName].set(route, rendered);
|
||||
return rendered;
|
||||
},
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue