rn-swiper-list
rn-swiper-list copied to clipboard
Avoid rendering all cards (performance)
When mounting <Swiper />, it process renderCard over all the item we provide in data.
We quickly encounter performance issues (and even app crashs) if we have a lot of data (a lot = 100 or above).
It would be great to have an option to avoid rendering cards depending on the current active index for example.
I have a development on this, but I can't add it right now because I don't have the time, but I will do it as soon as possible.
I forked locally and succeed in having 10.000 items by slicing the data in the Swiper component before rendering, and adjusting the SwipableCard index.
It works like a charm as long as I dont have to call programmatically the swipeLeft/swipeRight, nor call the swipeBack.
@Skipperlla If you have any recommandations or even a plan to finalize it, I'll be happy to create the PR and save you time.
I don't have a plan for the moment, since I'm very busy, I can usually update this library every 2 or 3 months in bulk, if you open the feature you want as a pr, I can spare time to read and merge the pr. @tilap
@Skipperlla @tilap I made a fork of the library which only renders 2 next and 2 previous cards. I'll make a PR when I have time. Using this method we can also implement loop features (#37)
@Skipperlla @tilap I made a fork of the library which only renders 2 next and 2 previous cards. I'll make a PR when I have time. Using this method we can also implement loop features (#37)
Any updates? Will appreciate looking at your pr
this weekend I will look at this and all other issues and pr's and close them, I apologize to all of you one by one for keeping you waiting so long @tilap @vanenshi @NeroN7F @umangloria
@Skipperlla @tilap I made a fork of the library which only renders 2 next and 2 previous cards. I'll make a PR when I have time. Using this method we can also implement loop features (#37)
Any updates? Will appreciate looking at your pr
Very sorry @NeroN7F, I am a little busy right now, I am just going to share the code here.
import { fixedForwardRef } from '@/utils/ref';
import React, {
RefObject,
useEffect,
useImperativeHandle,
useMemo,
type ForwardedRef,
} from 'react';
import {
SwiperCardOptions,
SwiperCardRefType,
SwiperOptions,
SwiperRefType,
} from '.';
import { SwipeableCard } from './SwiperCard';
import { useSwipeControls } from './hooks/useSwipeControls';
const renderSwipeable = <T,>(
item: T | undefined,
index: number,
renderCard: (item: T, index: number) => JSX.Element,
keyExtractor: ((item: T) => string) | undefined,
ref: RefObject<SwiperCardRefType> | undefined,
additionalProps: Omit<SwiperCardOptions, 'index'>,
) => {
if (!item) return null;
const key = keyExtractor ? keyExtractor(item) : index;
return (
<SwipeableCard key={key} ref={ref} index={index} {...additionalProps}>
{renderCard(item, index)}
</SwipeableCard>
);
};
const SwiperComponent = <T,>(
{
data,
onSwipedAll,
onIndexChange,
renderCard,
keyExtractor,
OverlayLabelBottom,
OverlayLabelLeft,
OverlayLabelRight,
OverlayLabelTop,
cardStyle,
disableBottomSwipe,
disableLeftSwipe,
disableRightSwipe,
disableTopSwipe,
inputOverlayLabelBottomOpacityRange,
inputOverlayLabelLeftOpacityRange,
inputOverlayLabelRightOpacityRange,
inputOverlayLabelTopOpacityRange,
outputOverlayLabelBottomOpacityRange,
onSwipeActive,
onSwipeBottom,
onSwipeEnd,
onSwipeLeft,
onSwipeRight,
onSwipeStart,
onSwipeTop,
outputOverlayLabelLeftOpacityRange,
outputOverlayLabelRightOpacityRange,
outputOverlayLabelTopOpacityRange,
rotateInputRange,
rotateOutputRange,
translateXRange,
translateYRange,
}: SwiperOptions<T>,
ref: ForwardedRef<SwiperRefType>,
) => {
const {
activeIndex,
setActiveIndex,
refs,
swipeRight,
swipeLeft,
swipeBack,
swipeTop,
swipeBottom,
jumpToCard,
} = useSwipeControls(data);
useImperativeHandle(
ref,
() => ({
swipeLeft,
swipeRight,
swipeBack,
swipeTop,
swipeBottom,
jumpToCard,
}),
[swipeLeft, swipeRight, swipeBack, swipeTop, swipeBottom, jumpToCard],
);
useEffect(() => {
if (activeIndex >= data.length) onSwipedAll?.();
}, [activeIndex, data.length, onIndexChange, onSwipedAll]);
useEffect(() => {
onIndexChange?.(activeIndex);
}, [activeIndex, onIndexChange]);
const cards = useMemo(() => {
const cardRenderingProps = {
activeIndex,
setActiveIndex,
OverlayLabelBottom,
OverlayLabelLeft,
OverlayLabelRight,
OverlayLabelTop,
cardStyle,
disableBottomSwipe,
disableLeftSwipe,
disableRightSwipe,
disableTopSwipe,
inputOverlayLabelBottomOpacityRange,
inputOverlayLabelLeftOpacityRange,
inputOverlayLabelRightOpacityRange,
inputOverlayLabelTopOpacityRange,
outputOverlayLabelBottomOpacityRange,
onSwipeActive,
onSwipeBottom,
onSwipeEnd,
onSwipeLeft,
onSwipeRight,
onSwipeStart,
onSwipeTop,
outputOverlayLabelLeftOpacityRange,
outputOverlayLabelRightOpacityRange,
outputOverlayLabelTopOpacityRange,
rotateInputRange,
rotateOutputRange,
translateXRange,
translateYRange,
} satisfies Omit<SwiperCardOptions, 'index'>;
return [
renderSwipeable(
data[activeIndex - 1],
activeIndex - 1,
renderCard,
keyExtractor,
refs[activeIndex - 1],
cardRenderingProps,
),
renderSwipeable(
data[activeIndex],
activeIndex,
renderCard,
keyExtractor,
refs[activeIndex],
cardRenderingProps,
),
renderSwipeable(
data[activeIndex + 1],
activeIndex + 1,
renderCard,
keyExtractor,
refs[activeIndex + 1],
cardRenderingProps,
),
renderSwipeable(
data[activeIndex + 2],
activeIndex + 2,
renderCard,
keyExtractor,
refs[activeIndex + 2],
cardRenderingProps,
),
].filter(Boolean);
}, [
activeIndex,
setActiveIndex,
OverlayLabelBottom,
OverlayLabelLeft,
OverlayLabelRight,
OverlayLabelTop,
cardStyle,
disableBottomSwipe,
disableLeftSwipe,
disableRightSwipe,
disableTopSwipe,
inputOverlayLabelBottomOpacityRange,
inputOverlayLabelLeftOpacityRange,
inputOverlayLabelRightOpacityRange,
inputOverlayLabelTopOpacityRange,
outputOverlayLabelBottomOpacityRange,
onSwipeActive,
onSwipeBottom,
onSwipeEnd,
onSwipeLeft,
onSwipeRight,
onSwipeStart,
onSwipeTop,
outputOverlayLabelLeftOpacityRange,
outputOverlayLabelRightOpacityRange,
outputOverlayLabelTopOpacityRange,
rotateInputRange,
rotateOutputRange,
translateXRange,
translateYRange,
data,
renderCard,
keyExtractor,
refs,
]);
return cards;
};
export const Swiper = fixedForwardRef(SwiperComponent);
it's very basic, I am sure @Skipperlla can make a better version of it 😁
a very important note: I had to change the activeIndex from shared value to a state, since in this version, sometimes the change of the activeIndex is not cause render and causes bad animation
Since I urgently needed this feature, I ended up rewriting the component from scratch. I’ve attached the code below for reference / if it can help you go further. It works with more than 1.000 items, as infinite swipe, and you can choose own many component to render. However it doesn't handle vertical swipes.
I’ll keep following this issue and will look into reintegrating it with my code if it meets my needs.
https://github.com/tilap/expo-photo-swipe/blob/main/src/components/Swiper.tsx
@Skipperlla Any updates? It's been a while since then. It makes it impossible to use this lib in the production
@NeroN7F I'm making a development about it but for now I found a bug that I can't bring the others after rendering, if you want to make a contribution about it I'll leave the link here https://github.com/Skipperlla/rn-swiper-list/pull/41
One problem I encountered during the development, were related to active index
I fixed it by changing the active index to state, instead of shared value. This is naturally going to have some impact on the animation. But we still manage to keep the 60 frame without a problem
On Thu, Dec 5, 2024 at 01:42 Omer @.***> wrote:
@NeroN7F https://github.com/NeroN7F I'm making a development about it but for now I found a bug that I can't bring the others after rendering, if you want to make a contribution about it I'll leave the link here #41 https://github.com/Skipperlla/rn-swiper-list/pull/41
— Reply to this email directly, view it on GitHub https://github.com/Skipperlla/rn-swiper-list/issues/36#issuecomment-2518665480, or unsubscribe https://github.com/notifications/unsubscribe-auth/AOV7D5VZD25V7IO7XHBUJD32D5443AVCNFSM6AAAAABOQIXNOGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKMJYGY3DKNBYGA . You are receiving this because you were mentioned.Message ID: @.***>
#42 @Skipperlla Fixed the problem as @vanenshi stated. However, programmatic swipes might skip card's "swipe like" animation.
Damn, I kinda remember fixing that problem, I’ll share it with you if I remember
On Thu, Dec 5, 2024 at 14:47 Temur @.***> wrote:
@Skipperlla https://github.com/Skipperlla Fixed the problem as @vanenshi https://github.com/vanenshi stated Here https://github.com/Skipperlla/rn-swiper-list/pull/42. However, programmatic swipes might skip card's swipe like animation.
— Reply to this email directly, view it on GitHub https://github.com/Skipperlla/rn-swiper-list/issues/36#issuecomment-2520020218, or unsubscribe https://github.com/notifications/unsubscribe-auth/AOV7D5XIQGBAQVZ2KSWNWWL2EAY3BAVCNFSM6AAAAABOQIXNOGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKMRQGAZDAMRRHA . You are receiving this because you were mentioned.Message ID: @.***>
@vanenshi Would be awesome. Will try to handle it myself these days otherwise
@vanenshi @NeroN7F If you mention me after you finish your pr developments, I can review
Bump
@pfcodes @NeroN7F said he was going to do the development here, so I'm stopping as much as I can in his pr. If I find the time, I'll take a look.
unfortunately I can't spend much time on this package because I'm too busy, but I'll do it as soon as possible, I'll look into it in a couple of weeks.
@Skipperlla Any updates on this?
https://github.com/Skipperlla/rn-swiper-list/pull/53 merged and published