react-snap-carousel icon indicating copy to clipboard operation
react-snap-carousel copied to clipboard

Infinite scroll

Open WillSmithTE opened this issue 2 years ago • 2 comments

Thanks a lot for the library, it's really great.

Is there any chance you have an example of someone using it to implement an infinite scroll? Right now I'm navigating back to the start, which works, but makes it obvious to the user that they're back at the start.

    const onNext = () => {
        if (activePageIndex === pages.length - 1) {
            goTo(0)
        } else {
            next()
        }
    }
    const onPrev = () => {
        if (activePageIndex === 0) {
            goTo(pages.length - 1)
        } else {
            prev()
        }
    }

Netflix is an example of an infinite carousel which doesn't look like you're going back to the start. Thanks!

WillSmithTE avatar Aug 17 '23 16:08 WillSmithTE

I'm afraid it's not currently possible out of the box.

I haven't prioritised it as a feature for two reasons:

  1. I think it's generally bad UX as users waste time cycling through items they've already seen, often not realising for a few pages 😖
  2. It could be challenging to (seamlessly) implement given react snap carousel uses native browser scrolling and native scrolling doesn't support looping.

Having said that I know developers do seem to like it and there must be a reason companies like Netflix implement it -- although I wouldn't be surprised if it's to keep users unfairly engaged for longer.

One workaround you could consider is, so long as you don't care about pagination (i.e. you can get away with just prev / next arrows like netflix), you could repeat the items in the DOM x times. I know browsers are pretty capable of scrolling large lists (1000s of items) so it shouldn't be a performance issue. e.g.

const items = Array.from({ length: 20 }).map((_, i) => ({
  id: i,
  src: `https://picsum.photos/500?idx=${i}`
}));

const App = () => (
  <Carousel
    items={Array.from({ length: 30 }).flatMap(() => items)}
    renderItem={({ item, isSnapPoint }) => (
      <CarouselItem key={item.id} isSnapPoint={isSnapPoint}>
        <img src={item.src} width="250" height="250" alt="" />
      </CarouselItem>
    )}
  />
);

You'd then could jump to the middle page so it's as good as "infinite" in both directions.

I would probably avoid doing it during SSR and only duplicate once hydrated on the client, that way you don't pay the cost over the wire. Granted it's pretty hacky, but probably reasonably effective for many use cases.

richardscarrott avatar Aug 17 '23 21:08 richardscarrott

Ok thanks for the suggestion, makes sense.

WillSmithTE avatar Aug 21 '23 19:08 WillSmithTE