From bb39a2e9da7ba2d89c9d5e55cc6d730a56edd7c0 Mon Sep 17 00:00:00 2001 From: Eric Vicenti Date: Tue, 3 May 2016 13:30:24 -0700 Subject: [PATCH] Reduce extra rendering in NavigationCard Summary: This adds a new SceneView with a shouldComponentUpdate policy of only re-rendering when the scene's state changes. This allows avoidance of extra re-renders. Results in a much smoother back-swipe gesture because we no longer re-render scenes as we transition from gesture to animation. Reviewed By: hedgerwang Differential Revision: D3219545 fb-gh-sync-id: 7c04e0e4ebb40d1e57ef7af11e2e54adf4f52aa0 fbshipit-source-id: 7c04e0e4ebb40d1e57ef7af11e2e54adf4f52aa0 --- Examples/UIExplorer/UIExplorerExampleList.js | 34 ++++++++++--------- .../NavigationExperimental/NavigationCard.js | 29 +++++++++++++++- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/Examples/UIExplorer/UIExplorerExampleList.js b/Examples/UIExplorer/UIExplorerExampleList.js index 29cef392201..5eb6a6b44ef 100644 --- a/Examples/UIExplorer/UIExplorerExampleList.js +++ b/Examples/UIExplorer/UIExplorerExampleList.js @@ -1,4 +1,11 @@ /** + * Copyright (c) 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * * The examples provided by Facebook are for non-commercial testing and * evaluation purposes only. * @@ -15,26 +22,21 @@ */ 'use strict'; +const ListView = require('ListView'); const React = require('react'); -const ReactNative = require('react-native'); +const StyleSheet = require('StyleSheet'); +const Text = require('Text'); +const TextInput = require('TextInput'); +const NavigationContainer = require('NavigationContainer'); +const TouchableHighlight = require('TouchableHighlight'); +const View = require('View'); const UIExplorerActions = require('./UIExplorerActions'); -const { - ListView, - NavigationExperimental, - StyleSheet, - Text, - TextInput, - TouchableHighlight, - View, -} = ReactNative; + const createExamplePage = require('./createExamplePage'); -const { - Container: NavigationContainer, -} = NavigationExperimental; import type { UIExplorerExample, -} from './UIExplorerList.ios' +} from './UIExplorerList.ios'; const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2, @@ -154,7 +156,7 @@ class UIExplorerExampleList extends React.Component { } _handleRowPress(exampleKey: string): void { - this.props.onNavigate(UIExplorerActions.ExampleAction(exampleKey)) + this.props.onNavigate(UIExplorerActions.ExampleAction(exampleKey)); } } @@ -167,7 +169,7 @@ function makeRenderable(example: any): ReactClass { UIExplorerExampleList = NavigationContainer.create(UIExplorerExampleList); UIExplorerExampleList.makeRenderable = makeRenderable; -var styles = StyleSheet.create({ +const styles = StyleSheet.create({ listContainer: { flex: 1, }, diff --git a/Libraries/CustomComponents/NavigationExperimental/NavigationCard.js b/Libraries/CustomComponents/NavigationExperimental/NavigationCard.js index 157c359d143..5dbff5d770f 100644 --- a/Libraries/CustomComponents/NavigationExperimental/NavigationCard.js +++ b/Libraries/CustomComponents/NavigationExperimental/NavigationCard.js @@ -51,6 +51,11 @@ import type { NavigationSceneRendererProps, } from 'NavigationTypeDefinition'; +type SceneViewProps = { + sceneRenderer: NavigationSceneRenderer, + sceneRendererProps: NavigationSceneRendererProps, +}; + type Props = NavigationSceneRendererProps & { onComponentRef: (ref: any) => void, panHandlers: ?NavigationPanPanHandlers, @@ -61,6 +66,25 @@ type Props = NavigationSceneRendererProps & { const {PropTypes} = React; +class SceneView extends React.Component { + + static propTypes = { + sceneRenderer: PropTypes.func.isRequired, + sceneRendererProps: NavigationPropTypes.SceneRenderer, + }; + + shouldComponentUpdate(nextProps: SceneViewProps, nextState: any): boolean { + return ( + nextProps.sceneRendererProps.scene.navigationState !== + this.props.sceneRendererProps.scene.navigationState + ); + } + + render(): ?ReactElement { + return this.props.sceneRenderer(this.props.sceneRendererProps); + } +} + /** * Component that renders the scene as card for the . */ @@ -107,7 +131,10 @@ class NavigationCard extends React.Component { pointerEvents={pointerEvents} ref={this.props.onComponentRef} style={[styles.main, viewStyle]}> - {renderScene(props)} + ); }