From 8097fcf4e7a10acc1563698182f5edcbc6596fb1 Mon Sep 17 00:00:00 2001 From: Hedger Wang Date: Wed, 25 May 2016 11:26:22 -0700 Subject: [PATCH] Fix NavigationTransitioner. Summary: - Address the issues reported at https://github.com/facebook/react-native/commit/7db7f78dc7d2b85843707f75565bcfcb538e8e51#commitcomment-17575647 - Fix the logic that reduces the scenes. - Fix the logic that computes the active scene for `renderOverlay`. Reviewed By: ericvicenti Differential Revision: D3344716 fbshipit-source-id: 3fce517ff1de212f412a77936012695bd2dcfc3c --- .../NavigationTransitioner.js | 14 +++++++- .../Reducer/NavigationScenesReducer.js | 16 ++++++++-- .../__tests__/NavigationScenesReducer-test.js | 32 +++++++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/Libraries/NavigationExperimental/NavigationTransitioner.js b/Libraries/NavigationExperimental/NavigationTransitioner.js index f319fe55b..49a999978 100644 --- a/Libraries/NavigationExperimental/NavigationTransitioner.js +++ b/Libraries/NavigationExperimental/NavigationTransitioner.js @@ -19,6 +19,8 @@ const React = require('React'); const StyleSheet = require('StyleSheet'); const View = require('View'); +const invariant = require('fbjs/lib/invariant'); + import type { NavigationActionCaller, NavigationAnimatedValue, @@ -219,13 +221,23 @@ class NavigationTransitioner extends React.Component { scenes, } = this.state; + const route = navigationState.routes[navigationState.index]; + + const activeScene = scenes.find(scene => { + return (!scene.isStale && scene.route === route) ? + scene : + undefined; + }); + + invariant(!!activeScene, 'no active scene found'); + return renderOverlay({ layout: this.state.layout, navigationState, onNavigate, position, progress, - scene: scenes[navigationState.index], + scene: activeScene, scenes, }); } diff --git a/Libraries/NavigationExperimental/Reducer/NavigationScenesReducer.js b/Libraries/NavigationExperimental/Reducer/NavigationScenesReducer.js index 98c5e76a3..a858a11e9 100644 --- a/Libraries/NavigationExperimental/Reducer/NavigationScenesReducer.js +++ b/Libraries/NavigationExperimental/Reducer/NavigationScenesReducer.js @@ -63,7 +63,6 @@ function areScenesShallowEqual( one.key === two.key && one.index === two.index && one.isStale === two.isStale && - one.route === two.route && one.route.key === two.route.key ); } @@ -147,7 +146,20 @@ function NavigationScenesReducer( staleScenes.forEach(mergeScene); freshScenes.forEach(mergeScene); - return nextScenes.sort(compareScenes); + nextScenes.sort(compareScenes); + + if (nextScenes.length !== scenes.length) { + return nextScenes; + } + + if (nextScenes.some( + (scene, index) => !areScenesShallowEqual(scenes[index], scene) + )) { + return nextScenes; + } + + // scenes haven't changed. + return scenes; } module.exports = NavigationScenesReducer; diff --git a/Libraries/NavigationExperimental/Reducer/__tests__/NavigationScenesReducer-test.js b/Libraries/NavigationExperimental/Reducer/__tests__/NavigationScenesReducer-test.js index 1788d0dd5..66373efe6 100644 --- a/Libraries/NavigationExperimental/Reducer/__tests__/NavigationScenesReducer-test.js +++ b/Libraries/NavigationExperimental/Reducer/__tests__/NavigationScenesReducer-test.js @@ -97,6 +97,38 @@ describe('NavigationScenesReducer', () => { ]); }); + it('gets same scenes', () => { + const state1 = { + index: 0, + routes: [{key: '1'}, {key: '2'}], + }; + + const state2 = { + index: 0, + routes: [{key: '1'}, {key: '2'}], + }; + + const scenes1 = NavigationScenesReducer([], state1, null); + const scenes2 = NavigationScenesReducer(scenes1, state2, state1); + expect(scenes1).toBe(scenes2); + }); + + it('gets different scenes', () => { + const state1 = { + index: 0, + routes: [{key: '1'}, {key: '2'}], + }; + + const state2 = { + index: 0, + routes: [{key: '2'}, {key: '1'}], + }; + + const scenes1 = NavigationScenesReducer([], state1, null); + const scenes2 = NavigationScenesReducer(scenes1, state2, state1); + expect(scenes1).not.toBe(scenes2); + }); + it('pops scenes', () => { // Transition from ['1', '2', '3'] to ['1', '2']. const scenes = testTransition([