react-native-pager-view icon indicating copy to clipboard operation
react-native-pager-view copied to clipboard

Wrapped pager for ease of use with separate components (without mapping function)

Open fendyk opened this issue 1 year ago • 0 comments

Describe the feature

This wraps the pagerview into a separate component and looks for the children within the pagerview and based on that will memoize the components.

Motivation

I struggled to find a way of using the usePagerView hook without a mapping function. For example when you want to show multiple components. So I thought of this idea and I just wanted to share this with everyone :)

Let me know what you think about this! Maybe someone else has an even better alternative? Happy coding!

Related Issues

Issue right now (look at comment):

export function PagerHookExample() {
  const { AnimatedPagerView, ref, ...rest } = usePagerView({ pagesAmount: 10 });
  
  return (
    <SafeAreaView style={styles.container}>
      <AnimatedPagerView
        testID="pager-view"
        ref={ref}
        style={styles.PagerView}
        initialPage={0}
        layoutDirection="ltr"
        overdrag={rest.overdragEnabled}
        scrollEnabled={rest.scrollEnabled}
        onPageScroll={rest.onPageScroll}
        onPageSelected={rest.onPageSelected}
        onPageScrollStateChanged={rest.onPageScrollStateChanged}
        pageMargin={10}
        orientation="horizontal"
      >
        {useMemo(
          () =>
            rest.pages.map((_, index) => ( // We're mapping here, but what if we want to show multiple components?
              <View
                testID="pager-view-content"
                key={index}
                style={{
                  flex: 1,
                  backgroundColor: '#fdc08e',
                  alignItems: 'center',
                  padding: 20,
                }}
                collapsable={false}
              >
                <LikeCount />
                <Text testID={`pageNumber${index}`}>
                  {`page number ${index}`}
                </Text>
              </View>
            )),
          [rest.pages]
        )}
      </AnimatedPagerView>
      <NavigationPanel {...rest} />
    </SafeAreaView>
  );
}

Step one: Create the component

import { forwardRef, Children, useMemo, useEffect } from "react";
import PagerView, { UsePagerViewProps } from "react-native-pager-view";

interface ListProps extends Omit<UsePagerViewProps, "ref"> {
	children: React.ReactNode;
	onListCountChange?: (count: number) => void;
}

const Pager = forwardRef<PagerView, ListProps>(
	({ children, onListCountChange, AnimatedPagerView, scrollEnabled, ...other }, ref) => {
		const childCount = Children.count(children);

		useEffect(() => {
			onListCountChange?.(childCount);
		}, [childCount]);

		return (
			<AnimatedPagerView
				useNext
				scrollEnabled={scrollEnabled || false}
				ref={ref}
				style={{ flex: 1 }}
				{...other}
			>
				{useMemo(
					() =>
						Children.map(children, (child, index) => {
							return child
						}),
					[children],
				)}
			</AnimatedPagerView>
		);
	},
);

export default Pager;

Step two: use the component using the usePagerView hook

export default function Screen() {
	const { activePage, ref, ...pagerViewProps } = usePagerView();
	return (
		<Pager
			activePage={activePage}
			ref={ref}
			{...pagerViewProps}
		>
			<UserProgressPage key={"1"} />
			<PlanStatsProgressPage key={"2"} />
			<ExerciseProgressPage key={"3"} />
		</Pager>
	);
}

fendyk avatar Nov 15 '24 08:11 fendyk