Mobile Development 10 min read

Performance Optimization of Round‑Trip Flight Booking UI in Ctrip's React Native Mobile App

This article details the redesign of Ctrip's domestic flight booking module to a dual‑column layout and shares the React Native gesture, animation, and performance optimization techniques that raised frame rates from ~40 fps to ~59 fps while handling double the data volume.

Ctrip Technology
Ctrip Technology
Ctrip Technology
Performance Optimization of Round‑Trip Flight Booking UI in Ctrip's React Native Mobile App

The author, a former Ctrip front‑end engineer, explains how the round‑trip flight booking flow in the Ctrip Chinese app was transformed from a multi‑page design to a single dual‑column page that displays outbound and return information side‑by‑side, improving conversion metrics.

The redesign required handling twice the data and nearly four times the component count, introducing complex gestures and animations that threatened performance on both iOS and Android.

Gesture handling relied on React Native's PanResponder . Common pitfalls such as ScrollView intercepting gestures on Android and unreliable dx values during fast swipes were addressed. Key callbacks include:

// When the user touches the screen, should we become responder?
onStartShouldSetPanResponderCapture
// When the user starts moving, should we become responder?
onMoveShouldSetPanResponderCapture
// Event bubbling phase – same checks
onStartShouldSetPanResponder
onMoveShouldSetPanResponder
// Gesture lifecycle callbacks
onPanResponderStart
onPanResponderMove
TouchUponPanResponderRelease
// When gesture is interrupted
onPanResponderTerminate
onPanResponderTerminationRequest

To prevent ScrollView from stealing the gesture, the solution disables scrolling via setNativeProps when the responder gains control and restores it after the gesture ends:

if (Platform.OS === 'ios')
    return;
this.firstTripSectionList.setNativeProps({ scrollEnabled: enable });
this.secondTripSectionList.setNativeProps({ scrollEnabled: enable });

Fast swipes sometimes yielded dx = 0 in onPanResponderTerminate . The fix was to read the accurate dx from onMoveShouldSetPanResponder and combine it with a temporary gesture direction variable.

Animation optimization focused on reducing the number of animated components, using native‑driver animations, and simplifying the animation hierarchy. Strategies included:

Minimizing component count and flattening the view hierarchy.

Using windowSize and decelerationRate to tune SectionList rendering.

Replacing simultaneous opacity and scale transitions with a single zIndex overlay technique.

Ensuring state changes do not trigger extra renders.

Leveraging native‑driven animations for transforms (e.g., translateX ) to avoid JS‑thread overhead.

Native driver usage example:

Animated.timing(this.animatedValue, {
    toValue: 0,
    duration: duration,
    easing: Easing.linear,
    useNativeDriver: enableNativeDriver
}).start();

Additional considerations involved the Android‑only collapsable property, which can cause layout‑only views to be removed from the native tree, potentially breaking animations; setting collapsable={false} for animated views resolves this.

Results : After the optimizations, gesture‑driven transitions achieved a stable 59 fps compared to the original ~40 fps, and business metrics such as conversion rates improved noticeably.

performanceiOSAndroidMobile UIReact Nativegesture handlingAnimation Optimization
Ctrip Technology
Written by

Ctrip Technology

Official Ctrip Technology account, sharing and discussing growth.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.