ホームページ > ウェブフロントエンド > jsチュートリアル > React-TanStack-Query を Next.js で次のレベルに引き上げる

React-TanStack-Query を Next.js で次のレベルに引き上げる

Linda Hamilton
リリース: 2025-01-22 20:40:10
オリジナル
506 人が閲覧しました

Taking React-TanStack-Query to the Next Level in Next.js

従来の fetch useState useEffect アプローチを React-TanStack-Query に置き換えることについての以前の議論を思い出してください。 QueryProvider の設定、基本的なクエリの作成、突然変異の処理などの基本を使用している場合は、おそらくすでにその利点を経験しているでしょう。 ただし、私たちはその機能の探索を始めたばかりです。

データの取得を大幅に強化し、アプリケーションのパフォーマンスを「良好」から「非常に高速」に変える高度なテクニックをさらに深く掘り下げてみましょう。

より強力な基盤を構築する

前のガイドでは、React-TanStack-Query を使用した基本的な映画リストを示しました。

<code class="language-javascript">const { data: movies, error, isLoading } = useQuery(['movies'], fetchMovies);</code>
ログイン後にコピー
ログイン後にコピー

これは素晴らしい出発点ですが、Netflix レベルの応答性を目指す場合はどうなるでしょうか? 技術を高めていきましょう。

優れたパフォーマンスのための高度なテクニック

1.インテリジェントなプリフェッチ (Netflix のような速度を実現)

最初の映画リストでは、ユーザーはクリック後に待つ必要がありました。これを大幅に改善できます:

<code class="language-javascript">// components/MovieList.jsx
import { useQueryClient } from '@tanstack/react-query';

export default function MovieList() {
  const queryClient = useQueryClient();

  // Leveraging our existing fetchMovies function
  const prefetchMovie = async (movieId) => {
    await queryClient.prefetchQuery({
      queryKey: ['movie', movieId],
      queryFn: () => fetchMovieDetails(movieId),
      // Maintain freshness for 5 minutes
      staleTime: 5 * 60 * 1000,
    });
  };

  return (
    <div className="grid grid-cols-4 gap-4">
      {movies.map(movie => (
        <div key={movie.id} onMouseEnter={() => prefetchMovie(movie.id)}
          className="movie-card"
        >
          {movie.title}
        </div>
      ))}
    </div>
  );
}</code>
ログイン後にコピー
ログイン後にコピー

ユーザーがムービーの上にマウスを移動すると、詳細が事前に読み込まれ、クリックするとすぐにアクセスできるようになりました。 ✨

2.突然変異の強化 (覚えていますか?)

私たちの最初の記事では、基本的な突然変異について説明しました。楽観的な更新でそれらを最適化しましょう:

<code class="language-javascript">// hooks/useUpdateMovie.js
export function useUpdateMovie() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: updateMovie,
    // The key improvement
    onMutate: async (newMovie) => {
      // Halt ongoing refetches
      await queryClient.cancelQueries(['movie', newMovie.id]);

      // Store current state (for rollback if needed)
      const previousMovie = queryClient.getQueryData(['movie', newMovie.id]);

      // Immediate (optimistic) update
      queryClient.setQueryData(['movie', newMovie.id], newMovie);

      return { previousMovie };
    },
    // Error handling
    onError: (err, newMovie, context) => {
      queryClient.setQueryData(
        ['movie', newMovie.id],
        context.previousMovie
      );
    },
  });
}</code>
ログイン後にコピー
ログイン後にコピー

3.並列データロード (無駄な待ち時間をなくす)

順次読み込みは過去のものです:

<code class="language-javascript">// pages/movie/[id].js
export default function MoviePage({ movieId }) {
  const results = useQueries({
    queries: [
      {
        queryKey: ['movie', movieId],
        queryFn: () => fetchMovie(movieId),
      },
      {
        queryKey: ['cast', movieId],
        queryFn: () => fetchCast(movieId),
      },
      {
        queryKey: ['reviews', movieId],
        queryFn: () => fetchReviews(movieId),
      },
    ],
  });

  if (results.some(result => result.isLoading)) {
    return <LoadingSpinner />;
  }

  const [movie, cast, reviews] = results.map(r => r.data);

  return <MovieDetails cast={cast} movie={movie} reviews={reviews} />;
}</code>
ログイン後にコピー
ログイン後にコピー

4.無限スクロールの実装 (効率的な方法)

ページ分割された例をシームレスな無限スクロールにアップグレードしてみましょう:

<code class="language-javascript">// components/InfiniteMovieList.jsx
import { useInfiniteQuery } from '@tanstack/react-query';
import { useInView } from 'react-intersection-observer';

export default function InfiniteMovieList() {
  const { ref, inView } = useInView();

  const {
    data,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
  } = useInfiniteQuery({
    queryKey: ['movies'],
    queryFn: fetchMoviePage,
    getNextPageParam: (lastPage) => lastPage.nextCursor,
  });

  useEffect(() => {
    if (inView && hasNextPage) {
      fetchNextPage();
    }
  }, [inView, hasNextPage]);

  return (
    <div>
      {data.pages.map((page) => (
        page.movies.map((movie) => (
          <MovieCard key={movie.id} movie={movie} />
        ))
      ))}

      <div ref={ref}>
        {isFetchingNextPage ? <LoadingSpinner /> : null}
      </div>
    </div>
  );
}</code>
ログイン後にコピー

5. Next.js 14 サーバー コンポーネントの活用

これは、最初の記事「Next.js 14 サーバー コンポーネントの統合」では利用できない機能です。

<code class="language-javascript">const { data: movies, error, isLoading } = useQuery(['movies'], fetchMovies);</code>
ログイン後にコピー
ログイン後にコピー

プロのヒント (教訓)

  1. 一貫したクエリ キー: 映画のクエリ キーを調整します:
<code class="language-javascript">// components/MovieList.jsx
import { useQueryClient } from '@tanstack/react-query';

export default function MovieList() {
  const queryClient = useQueryClient();

  // Leveraging our existing fetchMovies function
  const prefetchMovie = async (movieId) => {
    await queryClient.prefetchQuery({
      queryKey: ['movie', movieId],
      queryFn: () => fetchMovieDetails(movieId),
      // Maintain freshness for 5 minutes
      staleTime: 5 * 60 * 1000,
    });
  };

  return (
    <div className="grid grid-cols-4 gap-4">
      {movies.map(movie => (
        <div key={movie.id} onMouseEnter={() => prefetchMovie(movie.id)}
          className="movie-card"
        >
          {movie.title}
        </div>
      ))}
    </div>
  );
}</code>
ログイン後にコピー
ログイン後にコピー
  1. インテリジェントな再フェッチ: ウィンドウ フォーカスでの基本的な再フェッチを改善します:
<code class="language-javascript">// hooks/useUpdateMovie.js
export function useUpdateMovie() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: updateMovie,
    // The key improvement
    onMutate: async (newMovie) => {
      // Halt ongoing refetches
      await queryClient.cancelQueries(['movie', newMovie.id]);

      // Store current state (for rollback if needed)
      const previousMovie = queryClient.getQueryData(['movie', newMovie.id]);

      // Immediate (optimistic) update
      queryClient.setQueryData(['movie', newMovie.id], newMovie);

      return { previousMovie };
    },
    // Error handling
    onError: (err, newMovie, context) => {
      queryClient.setQueryData(
        ['movie', newMovie.id],
        context.previousMovie
      );
    },
  });
}</code>
ログイン後にコピー
ログイン後にコピー
  1. 堅牢なエラー処理: 基本的なエラー処理を強化します:
<code class="language-javascript">// pages/movie/[id].js
export default function MoviePage({ movieId }) {
  const results = useQueries({
    queries: [
      {
        queryKey: ['movie', movieId],
        queryFn: () => fetchMovie(movieId),
      },
      {
        queryKey: ['cast', movieId],
        queryFn: () => fetchCast(movieId),
      },
      {
        queryKey: ['reviews', movieId],
        queryFn: () => fetchReviews(movieId),
      },
    ],
  });

  if (results.some(result => result.isLoading)) {
    return <LoadingSpinner />;
  }

  const [movie, cast, reviews] = results.map(r => r.data);

  return <MovieDetails cast={cast} movie={movie} reviews={reviews} />;
}</code>
ログイン後にコピー
ログイン後にコピー

適切なテクニックの選択

  • 基本的なクエリ (最初の記事より): 単純なデータの取得に最適です。
  • プリフェッチ: ユーザーのアクションが予測可能な場合に最適です。
  • 並列クエリ: 複数の独立したデータセットが必要な場合に使用します。
  • 無限クエリ: スクロール可能な長いリストに適しています。
  • 楽観的なアップデート: 瞬時のユーザー エクスペリエンスを実現します。

結論

初期設定から大幅に進歩しました!これらの機能強化は、真に優れたユーザー エクスペリエンスを作成するために非常に重要です。

すべてを一度に実装する必要はないことに注意してください。基本から始めて、必要に応じてこれらの最適化を段階的に組み込んでいきます。

次回誰かがあなたのアプリケーションの速度についてコメントするとき、あなたはそれがなぜそれほど素晴らしいのかを正確に知ることになるでしょう。 ?

コーディングを楽しんでください! React-TanStack-Query は無限の可能性を提供します。次は何を調べましょう?

以上がReact-TanStack-Query を Next.js で次のレベルに引き上げるの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート