Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[@next] useNativeDriver: true in onPageScroll works with PagerView, but not LazyPagerView #576

Closed
SimpleCreations opened this issue Jun 14, 2022 · 6 comments

Comments

@SimpleCreations
Copy link

Description

When using Animated.event in onPageScroll of LazyPagerView and setting useNativeDriver to true, the animated values of position and offset do not get updated at all.
The same setup works as intended with the regular PagerView.
This leads to poor performance of animations based on the page position.

Reproducible Demo

Here's a code snippet which uses PagerView and where the animated values are properly updated:

import React, {useRef} from 'react';
import {Animated, SafeAreaView, StyleSheet, Text, View} from 'react-native';
import {PagerView} from 'react-native-pager-view';

const AnimatedPagerView = Animated.createAnimatedComponent(PagerView);

const App = () => {
  const position = useRef(new Animated.Value(0)).current;
  const offset = useRef(new Animated.Value(0)).current;
  const translateX = Animated.multiply(Animated.add(position, offset), 100);

  return (
    <SafeAreaView style={styles.container}>
      <Animated.View style={[styles.block, {transform: [{translateX}]}]} />
      <AnimatedPagerView
        style={styles.container}
        initialPage={0}
        onPageScroll={Animated.event([{nativeEvent: {position, offset}}], {
          useNativeDriver: true,
        })}>
        <View key="1" style={styles.page}>
          <Text>1</Text>
        </View>
        <View key="2" style={styles.page}>
          <Text>2</Text>
        </View>
        <View key="3" style={styles.page}>
          <Text>3</Text>
        </View>
      </AnimatedPagerView>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {flex: 1},
  block: {marginBottom: 20, width: 30, height: 30, backgroundColor: '#000'},
  page: {borderWidth: 1},
});

export default App;

Here's the same setup which uses LazyPagerView and where the animated values are always at 0:

import React, {useRef} from 'react';
import {Animated, SafeAreaView, StyleSheet, Text, View} from 'react-native';
import {LazyPagerView} from 'react-native-pager-view';

const AnimatedLazyPagerView = Animated.createAnimatedComponent(LazyPagerView);

const App = () => {
  const position = useRef(new Animated.Value(0)).current;
  const offset = useRef(new Animated.Value(0)).current;
  const translateX = Animated.multiply(Animated.add(position, offset), 100);

  const data = [1, 2, 3];
  const renderItem = ({item}) => (
    <View key={item} style={styles.page}>
      <Text>{item}</Text>
    </View>
  );
  const extractKey = item => item + '';

  return (
    <SafeAreaView style={styles.container}>
      <Animated.View style={[styles.block, {transform: [{translateX}]}]} />
      <AnimatedLazyPagerView
        style={styles.container}
        initialPage={0}
        onPageScroll={Animated.event([{nativeEvent: {position, offset}}], {
          useNativeDriver: true,
        })}
        data={data}
        renderItem={renderItem}
        keyExtractor={extractKey}
      />
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {flex: 1},
  block: {marginBottom: 20, width: 30, height: 30, backgroundColor: '#000'},
  page: {borderWidth: 1},
});

export default App;

Changing useNativeDriver: true to useNativeDriver: false restores the functionality, but degrades performance.

@SimpleCreations
Copy link
Author

I've noticed that removing the wrapper around LazyPagerViewImpl and exporting LazyPagerViewImpl instead restores the useNativeDriver functionality.
https://github.com/callstack/react-native-pager-view/blob/next/src/LazyPagerView.tsx#L33

Is there any reason this wrapper was added? I could make a PR removing it.

@troZee
Copy link
Member

troZee commented Jun 15, 2022

Is there any reason this wrapper was added? I could make a PR removing it.

@alpha0010 Could you help me with above question ?

@alpha0010
Copy link
Contributor

The wrapper dramatically reduced calls to the main render() function, which (depending on data, config, etc.) is heavy. If you do remove the wrapper, I recommend caching the renderChildren() call (for example, with memoize-one).

@SimpleCreations
Copy link
Author

@alpha0010 then I believe declaring LazyPagerViewImpl as PureComponent should have the same effect without the need for a wrapper or manual memoization. Or is there something I'm missing?

@alpha0010
Copy link
Contributor

Unfortunately, it has been too long since I worked on this for me to recall if I: did not test that, tested but it did not work, or maybe just implemented it wrong while testing (or maybe something else).

@troZee
Copy link
Member

troZee commented Dec 20, 2022

#673

@troZee troZee closed this as completed Dec 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants