Tips & Tricks

Cara Implement Infinite Scroll dengan Claude Code

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

mekanisme 無限scroll

無限scroll 、pengguna halaman末尾 近づく dan 自動的 次 データ 読み込むUIpola.SNSやニュースaplikasi おなじみ す 、performaやアクセシビリティ 考慮 implementasi 意外 dan 難しい juga .Claude Codeなら、best practices 沿ったimplementasi 素早くpembangunan bisa dilakukan.

Intersection Observerを使ったdasarimplementasi

> Intersection Observer 使った無限scroll Reactフック buatkan.
> ローディング状態 dan errorハンドリング juga 含めて。
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 };
}

penggunaan例 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="artikeldaftar">
      {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">読み込み中...</div>}
      {error && <div role="alert">エラーが発生しました。再試行してください。</div>}
      {!hasMore && <p>すべての記事を表示しました。</p>}
    </div>
  );
}

カーソルベースpagination backend

// オフセットベースより カーソルベース 方 performa 良い
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

Untuk Claude Codeを使えば、Intersection Observerベースの無限scrollからカーソルベースAPIまで一貫してpembangunanできます。大量データの描画performaには仮想scrollimplementasiを、pagination方式の比較, lihat ページネーション実装.

Intersection Observer API 詳細 MDN Web Docs silakan lihat.

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