callstack / react-native-pager-view

React Native wrapper for the Android ViewPager and iOS UIPageViewController.
MIT License
2.71k stars 415 forks source link

Lazy loading the components in viewpager #677

Open tahadar16 opened 1 year ago

tahadar16 commented 1 year ago

Lazy loading of components

I am unable to understand how do I stop the viewpager from loading all of my components at the same time. I want when the user selects a category and switches to that particular screen thats when it gets loaded. But right now its loading all of the components altogether

ttschnz commented 1 year ago

My interpretation of the docs is that offscreenPageLimit should do this, but I couldn't see it working on my app.

I found a workaround by returning an empty view on these items that are further away than x scrolls. Consider this example having 10 screens that count from 0 to 9:

function Screen() {
    const startIndex = 4;
    let [currentIndex, setCurrentIndex] = useState(startIndex);
    const renderLimit = 2; // render 2 pages before and after the current page
    return (
        <PagerView
            initialPage={startIndex}
            style={{ flex: 1 }}
            onPageSelected={(event) => {
                setCurrentIndex(event.nativeEvent.position);
            }}
        >
            {Array.from(Array(10).keys()).map((i, index) => {
                return (
                    <View
                        style={{
                            alignItems: "center",
                            backgroundColor: "white",
                            flex: 1,
                            justifyContent: "center",
                        }}
                        key={i}
                    >
                        {Math.abs(currentIndex - index) < renderLimit && (
                            <Text>{i}</Text>
                        )}
                    </View>
                );
            })}
        </PagerView>
    );
}

https://snack.expo.dev/@ttschnz/lazy-loading-the-components-in-viewpager

tahadar16 commented 1 year ago

I believe offscreenPageLimit works only for the Android platform as per the documents. I did see a few pull requests regarding the lazy loading but can't find any public methods in the repo for this requirement

Check this --> https://github.com/callstack/react-native-pager-view/pull/331 and this as well --> https://github.com/callstack/react-native-pager-view/releases/tag/v6.0.0-rc.0

abumalick commented 1 year ago

See the work around in https://github.com/callstack/react-native-pager-view/issues/673#issuecomment-1647351189

IronHeartDan commented 4 months ago

I made a wrapper for myself and it works pretty good. Hope it helps someone

import React, { useEffect, useState } from 'react';

const LazyComponent = ({ componentKey, currentKey, component, placeholder }) => {
    const [hasRendered, setHasRendered] = useState(false);

    useEffect(() => {
        if (!hasRendered && currentKey === componentKey)
            setHasRendered(true);
    }, [currentKey, componentKey, hasRendered]);

    if (hasRendered) return component;
    return placeholder || <></>;
};

export default LazyComponent;