Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7963add

Browse files
author
Eric Vicenti
committed
[ReactNative] Revamp Navigator scene cache strategy
Summary: Updating range is too complicated. We can keep cached versions of the previously rendered scenes in a map. @public Test Plan: Verify that the active scene is the only thing that get re-rendered, and that rendering doesn't happen during transitions or gestures. Test navigation thouroughly in AdsManager
1 parent 5e71d35 commit 7963add

File tree

1 file changed

+32
-85
lines changed

1 file changed

+32
-85
lines changed

Libraries/CustomComponents/Navigator/Navigator.js

Lines changed: 32 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
var AnimationsDebugModule = require('NativeModules').AnimationsDebugModule;
3131
var Dimensions = require('Dimensions');
3232
var InteractionMixin = require('InteractionMixin');
33+
var Map = require('Map');
3334
var NavigationContext = require('NavigationContext');
3435
var NavigatorBreadcrumbNavigationBar = require('NavigatorBreadcrumbNavigationBar');
3536
var NavigatorNavigationBar = require('NavigatorNavigationBar');
@@ -257,6 +258,8 @@ var Navigator = React.createClass({
257258
},
258259

259260
getInitialState: function() {
261+
this._renderedSceneMap = new Map();
262+
260263
var routeStack = this.props.initialRouteStack || [this.props.initialRoute];
261264
invariant(
262265
routeStack.length >= 1,
@@ -276,10 +279,6 @@ var Navigator = React.createClass({
276279
),
277280
idStack: routeStack.map(() => getuid()),
278281
routeStack,
279-
// `updatingRange*` allows us to only render the visible or staged scenes
280-
// On first render, we will render every scene in the initialRouteStack
281-
updatingRangeStart: 0,
282-
updatingRangeLength: routeStack.length,
283282
presentedIndex: initialRouteIndex,
284283
transitionFromIndex: null,
285284
activeGesture: null,
@@ -351,8 +350,6 @@ var Navigator = React.createClass({
351350
sceneConfigStack: nextRouteStack.map(
352351
this.props.configureScene
353352
),
354-
updatingRangeStart: 0,
355-
updatingRangeLength: nextRouteStack.length,
356353
presentedIndex: destIndex,
357354
activeGesture: null,
358355
transitionFromIndex: null,
@@ -829,11 +826,6 @@ var Navigator = React.createClass({
829826
return false;
830827
},
831828

832-
_resetUpdatingRange: function() {
833-
this.state.updatingRangeStart = 0;
834-
this.state.updatingRangeLength = this.state.routeStack.length;
835-
},
836-
837829
_getDestIndexWithinBounds: function(n) {
838830
var currentIndex = this.state.presentedIndex;
839831
var destIndex = currentIndex + n;
@@ -851,15 +843,8 @@ var Navigator = React.createClass({
851843

852844
_jumpN: function(n) {
853845
var destIndex = this._getDestIndexWithinBounds(n);
854-
var requestTransitionAndResetUpdatingRange = () => {
855-
this._enableScene(destIndex);
856-
this._transitionTo(destIndex);
857-
this._resetUpdatingRange();
858-
};
859-
this.setState({
860-
updatingRangeStart: destIndex,
861-
updatingRangeLength: 1,
862-
}, requestTransitionAndResetUpdatingRange);
846+
this._enableScene(destIndex);
847+
this._transitionTo(destIndex);
863848
},
864849

865850
jumpTo: function(route) {
@@ -891,18 +876,14 @@ var Navigator = React.createClass({
891876
var nextAnimationConfigStack = activeAnimationConfigStack.concat([
892877
this.props.configureScene(route),
893878
]);
894-
var requestTransitionAndResetUpdatingRange = () => {
895-
this._enableScene(destIndex);
896-
this._transitionTo(destIndex);
897-
this._resetUpdatingRange();
898-
};
899879
this.setState({
900880
idStack: nextIDStack,
901881
routeStack: nextStack,
902882
sceneConfigStack: nextAnimationConfigStack,
903-
updatingRangeStart: nextStack.length - 1,
904-
updatingRangeLength: 1,
905-
}, requestTransitionAndResetUpdatingRange);
883+
}, () => {
884+
this._enableScene(destIndex);
885+
this._transitionTo(destIndex);
886+
});
906887
},
907888

908889
_popN: function(n) {
@@ -958,10 +939,7 @@ var Navigator = React.createClass({
958939
idStack: nextIDStack,
959940
routeStack: nextRouteStack,
960941
sceneConfigStack: nextAnimationModeStack,
961-
updatingRangeStart: index,
962-
updatingRangeLength: 1,
963942
}, () => {
964-
this._resetUpdatingRange();
965943
if (index === this.state.presentedIndex) {
966944
this._emitWillFocus(route);
967945
this._emitDidFocus(route);
@@ -1034,67 +1012,15 @@ var Navigator = React.createClass({
10341012
var newStackLength = index + 1;
10351013
// Remove any unneeded rendered routes.
10361014
if (newStackLength < this.state.routeStack.length) {
1037-
var updatingRangeStart = newStackLength; // One past the top
1038-
var updatingRangeLength = this.state.routeStack.length - newStackLength + 1;
10391015
this.state.idStack.slice(newStackLength).map((removingId) => {
10401016
this._itemRefs[removingId] = null;
10411017
});
10421018
this.setState({
1043-
updatingRangeStart: updatingRangeStart,
1044-
updatingRangeLength: updatingRangeLength,
10451019
sceneConfigStack: this.state.sceneConfigStack.slice(0, newStackLength),
10461020
idStack: this.state.idStack.slice(0, newStackLength),
10471021
routeStack: this.state.routeStack.slice(0, newStackLength),
1048-
}, this._resetUpdatingRange);
1049-
}
1050-
},
1051-
1052-
_renderOptimizedScenes: function() {
1053-
// To avoid rendering scenes that are not visible, we use
1054-
// updatingRangeStart and updatingRangeLength to track the scenes that need
1055-
// to be updated.
1056-
1057-
// To avoid visual glitches, we never re-render scenes during a transition.
1058-
// We assume that `state.updatingRangeLength` will have a length during the
1059-
// initial render of any scene
1060-
var shouldRenderScenes = this.state.updatingRangeLength !== 0;
1061-
if (shouldRenderScenes) {
1062-
return (
1063-
<StaticContainer shouldUpdate={true}>
1064-
<View
1065-
style={styles.transitioner}
1066-
{...this.panGesture.panHandlers}
1067-
onTouchStart={this._handleTouchStart}
1068-
onResponderTerminationRequest={
1069-
this._handleResponderTerminationRequest
1070-
}>
1071-
{this.state.routeStack.map(this._renderOptimizedScene)}
1072-
</View>
1073-
</StaticContainer>
1074-
);
1022+
});
10751023
}
1076-
// If no scenes are changing, we can save render time. React will notice
1077-
// that we are rendering a StaticContainer in the same place, so the
1078-
// existing element will be updated. When React asks the element
1079-
// shouldComponentUpdate, the StaticContainer will return false, and the
1080-
// children from the previous reconciliation will remain.
1081-
return (
1082-
<StaticContainer shouldUpdate={false} />
1083-
);
1084-
},
1085-
1086-
_renderOptimizedScene: function(route, i) {
1087-
var shouldRenderScene =
1088-
i >= this.state.updatingRangeStart &&
1089-
i <= this.state.updatingRangeStart + this.state.updatingRangeLength;
1090-
var scene = shouldRenderScene ? this._renderScene(route, i) : null;
1091-
return (
1092-
<StaticContainer
1093-
key={'nav' + i}
1094-
shouldUpdate={shouldRenderScene}>
1095-
{scene}
1096-
</StaticContainer>
1097-
);
10981024
},
10991025

11001026
_renderScene: function(route, i) {
@@ -1146,9 +1072,30 @@ var Navigator = React.createClass({
11461072
},
11471073

11481074
render: function() {
1075+
var newRenderedSceneMap = new Map();
1076+
var scenes = this.state.routeStack.map((route, index) => {
1077+
var renderedScene;
1078+
if (this._renderedSceneMap.has(route) &&
1079+
index !== this.state.presentedIndex) {
1080+
renderedScene = this._renderedSceneMap.get(route);
1081+
} else {
1082+
renderedScene = this._renderScene(route, index);
1083+
}
1084+
newRenderedSceneMap.set(route, renderedScene);
1085+
return renderedScene;
1086+
});
1087+
this._renderedSceneMap = newRenderedSceneMap;
11491088
return (
11501089
<View style={[styles.container, this.props.style]}>
1151-
{this._renderOptimizedScenes()}
1090+
<View
1091+
style={styles.transitioner}
1092+
{...this.panGesture.panHandlers}
1093+
onTouchStart={this._handleTouchStart}
1094+
onResponderTerminationRequest={
1095+
this._handleResponderTerminationRequest
1096+
}>
1097+
{scenes}
1098+
</View>
11521099
{this._renderNavigationBar()}
11531100
</View>
11541101
);

0 commit comments

Comments
 (0)