Skip to content

Commit

Permalink
feat(js): lazy pager (#326)
Browse files Browse the repository at this point in the history
* chore: fix package dependency definition

* feat: draft js lazy view renderer

* fix: excessive renders when wrapped as animated component

* fix: reduce likelihood of becoming stuck on fast paging with small buffer

* chore: add lazy pager example

* docs: change wording

Co-authored-by: troZee <12766071+troZee@users.noreply.github.com>

Co-authored-by: troZee <12766071+troZee@users.noreply.github.com>
  • Loading branch information
alpha0010 and troZee committed Apr 29, 2021
1 parent 24f0405 commit bd0a058
Show file tree
Hide file tree
Showing 19 changed files with 486 additions and 53 deletions.
2 changes: 2 additions & 0 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { NavigationContainer, useNavigation } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { BasicPagerViewExample } from './BasicPagerViewExample';
import { KeyboardExample } from './KeyboardExample';
import { LazyPagerViewExample } from './LazyPagerViewExample';
import { OnPageScrollExample } from './OnPageScrollExample';
import { OnPageSelectedExample } from './OnPageSelectedExample';
import { ScrollablePagerViewExample } from './ScrollablePagerViewExample';
Expand All @@ -14,6 +15,7 @@ import PaginationDotsExample from './PaginationDotsExample';
const examples = [
{ component: BasicPagerViewExample, name: 'Basic Example' },
{ component: KeyboardExample, name: 'Keyboard Example' },
{ component: LazyPagerViewExample, name: 'Lazy Render Example' },
{ component: OnPageScrollExample, name: 'OnPageScroll Example' },
{ component: OnPageSelectedExample, name: 'OnPageSelected Example' },
{ component: HeadphonesCarouselExample, name: 'Headphones Carousel Example' },
Expand Down
4 changes: 2 additions & 2 deletions example/src/BasicPagerViewExample.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useMemo } from 'react';
import { StyleSheet, View, SafeAreaView, Animated, Text } from 'react-native';

import PagerView from 'react-native-pager-view';
import { PagerView } from 'react-native-pager-view';

import { LikeCount } from './component/LikeCount';
import { NavigationPanel } from './component/NavigationPanel';
Expand All @@ -10,7 +10,7 @@ import { useNavigationPanel } from './hook/useNavigationPanel';
const AnimatedPagerView = Animated.createAnimatedComponent(PagerView);

export function BasicPagerViewExample() {
const { ref, ...navigationPanel } = useNavigationPanel();
const { ref, ...navigationPanel } = useNavigationPanel<PagerView>();

return (
<SafeAreaView style={styles.container}>
Expand Down
2 changes: 1 addition & 1 deletion example/src/HeadphonesCarouselExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
ImageRequireSource,
} from 'react-native';
import type { PagerViewOnPageScrollEventData } from 'src/types';
import PagerView from 'react-native-pager-view';
import { PagerView } from 'react-native-pager-view';

const data = [
{
Expand Down
4 changes: 2 additions & 2 deletions example/src/KeyboardExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
Animated,
} from 'react-native';
import { Colors } from 'react-native/Libraries/NewAppScreen';
import PagerView from 'react-native-pager-view';
import { PagerView } from 'react-native-pager-view';
import { logoUrl } from './utils';

import { NavigationPanel } from './component/NavigationPanel';
Expand All @@ -37,7 +37,7 @@ const Page = ({ title, description, onPress, buttonTitle }: PageProps) => {
const AnimatedPagerView = Animated.createAnimatedComponent(PagerView);

export function KeyboardExample() {
const { ref, ...navigationPanel } = useNavigationPanel(2);
const { ref, ...navigationPanel } = useNavigationPanel<PagerView>(2);
const { setPage } = navigationPanel;
return (
<SafeAreaView style={styles.flex}>
Expand Down
70 changes: 70 additions & 0 deletions example/src/LazyPagerViewExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React from 'react';
import { Image, StyleSheet, View, SafeAreaView, Animated } from 'react-native';

import { LazyPagerView } from 'react-native-pager-view';

import { LikeCount } from './component/LikeCount';
import { NavigationPanel } from './component/NavigationPanel';
import { useNavigationPanel } from './hook/useNavigationPanel';
import type { CreatePage } from './utils';

const AnimatedPagerView = Animated.createAnimatedComponent(LazyPagerView);

function keyExtractor(page: CreatePage) {
return `${page.key}`;
}

function renderItem({ item }: { item: CreatePage }) {
return (
<View style={item.style}>
<Image style={styles.image} source={item.imgSource} />
<LikeCount />
</View>
);
}

export function LazyPagerViewExample() {
const { ref, ...navigationPanel } = useNavigationPanel<
LazyPagerView<unknown>
>();

return (
<SafeAreaView style={styles.container}>
<AnimatedPagerView
ref={ref}
style={styles.PagerView}
initialPage={0}
overdrag={navigationPanel.overdragEnabled}
scrollEnabled={navigationPanel.scrollEnabled}
onPageScroll={navigationPanel.onPageScroll}
onPageSelected={navigationPanel.onPageSelected}
onPageScrollStateChanged={navigationPanel.onPageScrollStateChanged}
pageMargin={10}
// Lib does not support dynamically orientation change
orientation="horizontal"
// Lib does not support dynamically transitionStyle change
transitionStyle="scroll"
showPageIndicator={navigationPanel.dotsEnabled}
data={navigationPanel.pages}
keyExtractor={keyExtractor}
renderItem={renderItem}
/>
<NavigationPanel {...navigationPanel} />
</SafeAreaView>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
},
image: {
width: 300,
height: 200,
padding: 20,
},
PagerView: {
flex: 1,
},
});
4 changes: 2 additions & 2 deletions example/src/OnPageScrollExample.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { StyleSheet, Text, View, SafeAreaView, Animated } from 'react-native';
import PagerView from 'react-native-pager-view';
import { PagerView } from 'react-native-pager-view';
import { ScrollView, TouchableOpacity } from 'react-native-gesture-handler';
import { ProgressBar } from './component/ProgressBar';
import { useNavigationPanel } from './hook/useNavigationPanel';
Expand All @@ -9,7 +9,7 @@ import { NavigationPanel } from './component/NavigationPanel';
const AnimatedPagerView = Animated.createAnimatedComponent(PagerView);

export function OnPageScrollExample() {
const { ref, ...navigationPanel } = useNavigationPanel(5);
const { ref, ...navigationPanel } = useNavigationPanel<PagerView>(5);
const { activePage, setPage, progress, pages } = navigationPanel;

return (
Expand Down
7 changes: 5 additions & 2 deletions example/src/OnPageSelectedExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
Animated,
} from 'react-native';

import PagerView from 'react-native-pager-view';
import { PagerView } from 'react-native-pager-view';
import { NavigationPanel } from './component/NavigationPanel';
import { useNavigationPanel } from './hook/useNavigationPanel';

Expand All @@ -19,7 +19,10 @@ export const OnPageSelectedExample = () => {
const callback = React.useCallback((position: number) => {
Alert.alert('Hey', `You are on ${position + 1} page`);
}, []);
const { ref, ...navigationPanel } = useNavigationPanel(10, callback);
const { ref, ...navigationPanel } = useNavigationPanel<PagerView>(
10,
callback
);

return (
<SafeAreaView style={styles.flex}>
Expand Down
3 changes: 2 additions & 1 deletion example/src/PaginationDotsExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
Animated,
Dimensions,
} from 'react-native';
import PagerView, {
import {
PagerView,
PagerViewOnPageScrollEventData,
} from 'react-native-pager-view';

Expand Down
2 changes: 1 addition & 1 deletion example/src/ScrollViewInsideExample.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import PagerView from 'react-native-pager-view';
import { PagerView } from 'react-native-pager-view';
import React from 'react';
import { useState } from 'react';
import { View, StyleSheet, Button, ScrollView, Animated } from 'react-native';
Expand Down
4 changes: 2 additions & 2 deletions example/src/ScrollablePagerViewExample.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import PagerView from 'react-native-pager-view';
import { PagerView } from 'react-native-pager-view';
import React from 'react';
import { ScrollView, View, Image, StyleSheet, Animated } from 'react-native';
import { NavigationPanel } from './component/NavigationPanel';
Expand All @@ -9,7 +9,7 @@ const HEIGHT = 300;
const AnimatedPagerView = Animated.createAnimatedComponent(PagerView);

export const ScrollablePagerViewExample = (): JSX.Element => {
const { ref, ...navigationPanel } = useNavigationPanel();
const { ref, ...navigationPanel } = useNavigationPanel<PagerView>();

return (
<>
Expand Down
6 changes: 3 additions & 3 deletions example/src/hook/useNavigationPanel.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type {
default as PagerView,
Pageable,
PageScrollStateChangedNativeEvent,
PagerViewOnPageScrollEventData,
PagerViewOnPageSelectedEventData,
Expand All @@ -19,11 +19,11 @@ export interface EventLog {
const getBasePages = (pages: number) =>
new Array(pages).fill('').map((_v, index) => createPage(index));

export function useNavigationPanel(
export function useNavigationPanel<T extends Pageable>(
pagesAmount: number = 10,
onPageSelectedCallback: (position: number) => void = () => {}
) {
const ref = useRef<PagerView>(null);
const ref = useRef<T>(null);
const [pages, setPages] = useState<CreatePage[]>(
useMemo(() => getBasePages(pagesAmount), [pagesAmount])
);
Expand Down
3 changes: 2 additions & 1 deletion example/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const IMAGE_URIS = [
];
export const thumbsUp = '\uD83D\uDC4D';
export const logoUrl =
'https://raw.githubusercontent.com/react-native-community/react-native-viewpager/master/docs/viewpager-logo.png';
'https://raw.githubusercontent.com/callstack/react-native-pager-view/master/img/viewpager-logo.png';

export type CreatePage = {
key: number;
Expand All @@ -25,6 +25,7 @@ export const createPage = (key: number): CreatePage => {
style: {
backgroundColor: BGCOLOR[key % BGCOLOR.length],
alignItems: 'center',
flex: 1,
padding: 20,
},
imgSource: { uri: IMAGE_URIS[key % BGCOLOR.length] },
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"prettier": "^2.0.5",
"react": "16.13.1",
"react-native": "0.63.4",
"react-native-builder-bob": "^",
"react-native-builder-bob": "^0.18.1",
"release-it": "^14.2.2",
"typescript": "^4.1.3"
},
Expand Down

0 comments on commit bd0a058

Please sign in to comment.