最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to avoid umping Issue using ShadCN Carousel with Server-Side Pagination NextJS? - Stack Overflow

programmeradmin3浏览0评论

I’m using the ShadCN Carousel in my Next.js app and trying to integrate it with server-side paginated API data.

The issue I’m facing is that the scrolling is not smooth—whenever new data is loaded, I notice a UI jump or flicker. It seems like the carousel recalculates the item sizes, causing an abrupt shift instead of a seamless transition.

Has anyone experienced this before? Is there a known solution or best practice for handling pagination smoothly in the ShadCN carousel?

Thanks in advance!

const PaginatedCarousel = ({ initialData, type }) => {
  const [data, setData] = useState(initialData?.results || [])
  const [currentPage, setCurrentPage] = useState(1)
  const [carouselApi, setCarouselApi] = useState(null)
  const [isPending, startTransition] = useTransition()
  const page_count = initialData?.page_count

  useEffect(() => {
    if (!carouselApi) return

    const handleSelect = async () => {
      const currentIndex = carouselApi.selectedScrollSnap()
      const totalSlides = carouselApi.scrollSnapList().length

      if (
        currentIndex >= totalSlides - 3 &&
        currentPage < page_count &&
        !isPending
      ) {
        const newPage = currentPage + 1
        startTransition(async () => {
          const newData = await fetchMoreCourses({ type, page: newPage })

          if (newData?.results?.length) {
            setData((prev) => [...prev, ...newData.results])
            setCurrentPage(newPage)
          }
        })
      }
    }

    carouselApi.on('select', handleSelect)

    return () => {
      carouselApi.off('select', handleSelect)
    }
  }, [carouselApi, data, currentPage, type, page_count, isPending])

  return (
    <div className="flex flex-col gap-12 w-11/12">
      <div className="flex items-center justify-between">
        <span className="m:text-2xl text-xl text-neutrals-50 font-clash not-italic leading-9 font-extramedium">
          {MAPPED_TITLE[type]}
        </span>

        <div className="flex items-center gap-5">
          <Image
            width={11}
            height={18}
            src={'/images/prevArrow.svg'}
            alt={'prev-arrow'}
            className={'cursor-pointer'}
            onClick={() => carouselApi && carouselApi.scrollPrev()}
          />
          <Image
            width={11}
            height={18}
            src={'/images/nextArrow.svg'}
            alt={'next-arrow'}
            className={'cursor-pointer'}
            onClick={() => carouselApi && carouselApi.scrollNext()}
          />
        </div>
      </div>

      <div className="w-full overflow-hidden">
        <Carousel className="w-full relative" setApi={setCarouselApi}>
          <CarouselContent className="flex space-x-2">
            {data.map((course) => (
              <CardsOrchestrator course={course} type={type} key={course.id} />
            ))}

            {isPending && <SkeletonCard type={type} />}
          </CarouselContent>
        </Carousel>
      </div>
    </div>
  )
}

发布评论

评论列表(0)

  1. 暂无评论