From 59803f54d64f85c8e46c1ebc70613a70a812f53a Mon Sep 17 00:00:00 2001 From: Satyajit Sahoo Date: Wed, 1 Jan 2020 16:26:51 +0100 Subject: [PATCH] fix: improve gesture performance --- packages/stack/src/views/Stack/Card.tsx | 20 ++++++-- .../stack/src/views/Stack/CardContainer.tsx | 3 -- packages/stack/src/views/Stack/CardStack.tsx | 3 -- packages/stack/src/views/Stack/StackView.tsx | 47 ++++++++++--------- 4 files changed, 43 insertions(+), 30 deletions(-) diff --git a/packages/stack/src/views/Stack/Card.tsx b/packages/stack/src/views/Stack/Card.tsx index 18fed77f..1bb75fff 100755 --- a/packages/stack/src/views/Stack/Card.tsx +++ b/packages/stack/src/views/Stack/Card.tsx @@ -105,6 +105,11 @@ export default class Card extends React.Component { if ( this.getAnimateToValue(this.props) !== this.getAnimateToValue(prevProps) ) { + // We need to trigger the animation when route was closed + // Thr route might have been closed by a `POP` action or by a gesture + // When route was closed due to a gesture, the animation would've happened already + // It's still important to trigger the animation so that `onClose` is called + // If `onClose` is not called, cleanup step won't be performed for gestures this.animate({ closing }); } } @@ -132,7 +137,7 @@ export default class Card extends React.Component { closing, velocity, }: { - closing: boolean | undefined; + closing?: boolean; velocity?: number; }) => { const { @@ -143,6 +148,11 @@ export default class Card extends React.Component { onTransitionStart, } = this.props; + const toValue = this.getAnimateToValue({ + ...this.props, + closing, + }); + const spec = closing ? transitionSpec.close : transitionSpec.open; const animation = @@ -153,7 +163,7 @@ export default class Card extends React.Component { ...spec.config, velocity, useNativeDriver: true, - toValue: this.getAnimateToValue(this.props), + toValue, }).start(({ finished }) => { if (finished) { if (closing) { @@ -169,7 +179,11 @@ export default class Card extends React.Component { closing, layout, gestureDirection, - }: Props) => { + }: { + closing?: boolean; + layout: Layout; + gestureDirection: GestureDirection; + }) => { if (!closing) { return 0; } diff --git a/packages/stack/src/views/Stack/CardContainer.tsx b/packages/stack/src/views/Stack/CardContainer.tsx index 8a77cacf..0cc5898e 100644 --- a/packages/stack/src/views/Stack/CardContainer.tsx +++ b/packages/stack/src/views/Stack/CardContainer.tsx @@ -30,7 +30,6 @@ type Props = TransitionPreset & { renderScene: (props: { route: Route }) => React.ReactNode; onOpenRoute: (props: { route: Route }) => void; onCloseRoute: (props: { route: Route }) => void; - onGoBack: (props: { route: Route }) => void; onTransitionStart?: ( props: { route: Route }, closing: boolean @@ -73,7 +72,6 @@ export default function CardContainer({ index, layout, onCloseRoute, - onGoBack, onOpenRoute, onPageChangeCancel, onPageChangeConfirm, @@ -109,7 +107,6 @@ export default function CardContainer({ } onTransitionStart?.({ route: scene.route }, closing); - closing && onGoBack({ route: scene.route }); }; const insets = { diff --git a/packages/stack/src/views/Stack/CardStack.tsx b/packages/stack/src/views/Stack/CardStack.tsx index 0904014f..d1e91574 100755 --- a/packages/stack/src/views/Stack/CardStack.tsx +++ b/packages/stack/src/views/Stack/CardStack.tsx @@ -46,7 +46,6 @@ type Props = { routes: Route[]; openingRouteKeys: string[]; closingRouteKeys: string[]; - onGoBack: (props: { route: Route }) => void; onOpenRoute: (props: { route: Route }) => void; onCloseRoute: (props: { route: Route }) => void; getPreviousRoute: (props: { @@ -360,7 +359,6 @@ export default class CardStack extends React.Component { closingRouteKeys, onOpenRoute, onCloseRoute, - onGoBack, getPreviousRoute, getGesturesEnabled, renderHeader, @@ -527,7 +525,6 @@ export default class CardStack extends React.Component { onCloseRoute={onCloseRoute} onTransitionStart={onTransitionStart} onTransitionEnd={onTransitionEnd} - onGoBack={onGoBack} gestureEnabled={index !== 0 && getGesturesEnabled({ route })} gestureVelocityImpact={gestureVelocityImpact} gestureDirection={gestureDirection} diff --git a/packages/stack/src/views/Stack/StackView.tsx b/packages/stack/src/views/Stack/StackView.tsx index c0f4290b..728634b9 100644 --- a/packages/stack/src/views/Stack/StackView.tsx +++ b/packages/stack/src/views/Stack/StackView.tsx @@ -266,18 +266,6 @@ class StackView extends React.Component { return ; }; - private handleGoBack = ({ route }: { route: Route }) => { - const { state, navigation } = this.props; - - // This event will trigger when a gesture ends - // We need to perform the transition before removing the route completely - navigation.dispatch({ - ...StackActions.pop(), - source: route.key, - target: state.key, - }); - }; - private handleOpenRoute = ({ route }: { route: Route }) => { this.setState(state => ({ routes: state.replacingRouteKeys.length @@ -290,15 +278,33 @@ class StackView extends React.Component { }; private handleCloseRoute = ({ route }: { route: Route }) => { - // This event will trigger when the animation for closing the route ends - // In this case, we need to clean up any state tracking the route and pop it immediately + const { state, navigation } = this.props; - // @ts-ignore - this.setState(state => ({ - routes: state.routes.filter(r => r.key !== route.key), - openingRouteKeys: state.openingRouteKeys.filter(key => key !== route.key), - closingRouteKeys: state.closingRouteKeys.filter(key => key !== route.key), - })); + if (state.routes.find(r => r.key === route.key)) { + // If a route exists in state, trigger a pop + // This will happen in when the route was closed from the card component + // e.g. When the close animation triggered from a gesture ends + // For the cleanup, the card needs to call this function again from its componentDidUpdate + navigation.dispatch({ + ...StackActions.pop(), + source: route.key, + target: state.key, + }); + } else { + // Otherwise, the animation was triggered due to a route removal + // In this case, we need to clean up any state tracking the route and pop it immediately + + // @ts-ignore + this.setState(state => ({ + routes: state.routes.filter(r => r.key !== route.key), + openingRouteKeys: state.openingRouteKeys.filter( + key => key !== route.key + ), + closingRouteKeys: state.closingRouteKeys.filter( + key => key !== route.key + ), + })); + } }; private handleTransitionStart = ( @@ -355,7 +361,6 @@ class StackView extends React.Component { routes={routes} openingRouteKeys={openingRouteKeys} closingRouteKeys={closingRouteKeys} - onGoBack={this.handleGoBack} onOpenRoute={this.handleOpenRoute} onCloseRoute={this.handleCloseRoute} onTransitionStart={this.handleTransitionStart}