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

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

Open
fendyk opened this issue Nov 15, 2024 · 0 comments

Comments

@fendyk
Copy link

fendyk commented Nov 15, 2024

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>
	);
}
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

1 participant