Tips & Tricks

Cara Implement Infinite Scroll dengan Claude Code

Pelajari cara implement infinite scroll pakai Claude Code. Dilengkapi contoh kode praktis dan panduan langkah demi langkah.

Mekanisme Infinite Scroll

Infinite scroll adalah UI pattern di mana data berikutnya otomatis di-load begitu user mendekati bagian bawah halaman. Pattern ini familiar di medsos dan aplikasi berita, tapi implementasinya yang mempertimbangkan performa dan aksesibilitas kadang lebih sulit dari yang dibayangkan. Pakai Claude Code, kamu bisa bangun implementasinya sesuai best practices dengan cepat.

Implementasi Dasar Pakai Intersection Observer

> Buat React hook infinite scroll pakai Intersection Observer.
> Sertakan state loading dan error handling.
import { useEffect, useRef, useState, useCallback } from 'react';

interface UseInfiniteScrollOptions<T> {
  fetchFn: (page: number) => Promise<{ data: T[]; hasMore: boolean }>;
  initialPage?: number;
  threshold?: number;
}

function useInfiniteScroll<T>({ fetchFn, initialPage = 1, threshold = 0.8 }: UseInfiniteScrollOptions<T>) {
  const [items, setItems] = useState<T[]>([]);
  const [page, setPage] = useState(initialPage);
  const [loading, setLoading] = useState(false);
  const [hasMore, setHasMore] = useState(true);
  const [error, setError] = useState<Error | null>(null);
  const observerRef = useRef<IntersectionObserver | null>(null);

  const lastElementRef = useCallback(
    (node: HTMLElement | null) => {
      if (loading) return;
      if (observerRef.current) observerRef.current.disconnect();

      observerRef.current = new IntersectionObserver(
        (entries) => {
          if (entries[0].isIntersecting && hasMore) {
            setPage((prev) => prev + 1);
          }
        },
        { threshold }
      );

      if (node) observerRef.current.observe(node);
    },
    [loading, hasMore, threshold]
  );

  useEffect(() => {
    let cancelled = false;
    setLoading(true);
    setError(null);

    fetchFn(page)
      .then((result) => {
        if (!cancelled) {
          setItems((prev) => [...prev, ...result.data]);
          setHasMore(result.hasMore);
        }
      })
      .catch((err) => { if (!cancelled) setError(err); })
      .finally(() => { if (!cancelled) setLoading(false); });

    return () => { cancelled = true; };
  }, [page, fetchFn]);

  return { items, loading, hasMore, error, lastElementRef };
}

Contoh Penggunaan di Komponen

function ArticleList() {
  const fetchArticles = useCallback(async (page: number) => {
    const res = await fetch(`/api/articles?page=${page}&limit=20`);
    const data = await res.json();
    return { data: data.articles, hasMore: data.hasMore };
  }, []);

  const { items, loading, hasMore, error, lastElementRef } = useInfiniteScroll({
    fetchFn: fetchArticles,
  });

  return (
    <div role="feed" aria-busy={loading} aria-label="Daftar artikel">
      {items.map((article, index) => (
        <article
          key={article.id}
          ref={index === items.length - 1 ? lastElementRef : null}
          aria-posinset={index + 1}
          aria-setsize={hasMore ? -1 : items.length}
        >
          <h2>{article.title}</h2>
          <p>{article.summary}</p>
        </article>
      ))}

      {loading && <div aria-live="polite">Memuat...</div>}
      {error && <div role="alert">Terjadi error. Silakan coba lagi.</div>}
      {!hasMore && <p>Semua artikel sudah ditampilkan.</p>}
    </div>
  );
}

Pagination Berbasis Cursor di Backend

// Cursor-based biasanya performa-nya lebih baik daripada offset-based
app.get('/api/articles', async (req, res) => {
  const limit = Math.min(Number(req.query.limit) || 20, 100);
  const cursor = req.query.cursor as string | undefined;

  const where = cursor ? { id: { gt: cursor } } : {};

  const articles = await prisma.article.findMany({
    where,
    take: limit + 1,
    orderBy: { id: 'asc' },
  });

  const hasMore = articles.length > limit;
  const data = hasMore ? articles.slice(0, -1) : articles;

  res.json({
    data,
    hasMore,
    nextCursor: hasMore ? data[data.length - 1].id : null,
  });
});

Summary

Pakai Claude Code, mulai dari infinite scroll berbasis Intersection Observer sampai API berbasis cursor, semuanya bisa dibangun secara konsisten. Untuk performa rendering data dalam jumlah besar, lihat implementasi virtual scroll, dan untuk perbandingan metode pagination, lihat implementasi pagination.

Untuk detail Intersection Observer API, lihat MDN Web Docs.

#Claude Code #infinite scroll #React #performance #UX

Tingkatkan alur kerja Claude Code kamu

50 template prompt yang sudah teruji, siap copy-paste ke Claude Code sekarang juga.

Gratis

PDF Gratis: Cheatsheet Claude Code dalam 5 Menit

Perintah penting, pintasan, dan contoh prompt dalam satu halaman siap cetak.

Unduh PDF
M

Tentang Penulis

Masa

Engineer yang aktif menggunakan Claude Code. Mengelola claudecode-lab.com, media teknologi 10 bahasa dengan lebih dari 2.000 halaman.