Next.js 13 では React Server Components が導入され、開発者はコンポーネントをパフォーマンスのためにサーバー上で、または対話性のためにクライアント上でレンダリングする場所と方法を選択できるようになりました。この柔軟性により、速度と動的な機能を組み合わせたアプリを構築できます。
この記事では、基本だけでなく、動的で効率的なアプリを構築する際によく必要となる、クライアント コンポーネント内でサーバー コンポーネントを使用する方法についても詳しく説明します。
サーバー コンポーネントは完全にサーバー上でレンダリングされ、クライアント側の JavaScript は必要ありません。これらは、ヘッダー、フッター、さらにはユーザーの操作を必要としないデータ駆動型コンポーネントなどの静的コンテンツに最適です。
// app/components/Header.js export default function Header() { return ( <header> <h1>My Static Header</h1> </header> ); }
このコンポーネントはサーバー上でレンダリングされ、クライアント側の操作を一切含まないため、JavaScript の使用量が少なくなり、読み込みが速くなります。
// app/components/PostList.js export default async function PostList() { const res = await fetch('https://jsonplaceholder.typicode.com/posts'); const posts = await res.json(); return ( <ul> {posts.slice(0, 5).map((post) => ( <li key={post.id}>{post.title}</li> ))} </ul> ); }
この PostList コンポーネントはサーバー上のデータをフェッチし、事前にレンダリングされた HTML をクライアントに送信して、読み込み時間を短縮します。
クライアント コンポーネントは、フォーム入力、イベント リスナー、動的コンテンツなどの対話性が必要な場合に不可欠です。これらのコンポーネントは、クライアント上で JavaScript を使用してユーザー操作を処理します。
// app/components/SearchBar.js 'use client'; // This makes the component a client component import { useState } from 'react'; export default function SearchBar() { const [searchTerm, setSearchTerm] = useState(''); return ( <div> <input type="text" value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} placeholder="Search..." /> <p>Searching for: {searchTerm}</p> </div> ); }
SearchBar は対話型であるため、クライアント コンポーネントである必要があります。 useState フックとその他の React フックは、クライアント コンポーネントでのみ使用できます。
サーバー コンポーネントとクライアント コンポーネントを組み合わせるユースケースがあるかもしれないので、次にその方法について説明しましょう:
Next.js 13 の核となる強みは、サーバー コンポーネントとクライアント コンポーネントを組み合わせる機能です。ベスト プラクティスは、デフォルトでサーバー コンポーネントを使用し、クライアント コンポーネントをコンポーネント ツリーのできるだけ深いところにプッシュすることです。
// app/layout.js import SearchBar from './components/SearchBar'; export default function Layout({ children }) { return ( <div> <header>My Blog</header> <SearchBar /> {/* Client component for interactivity */} {children} </div> ); }
SearchBar コンポーネントはクライアント側の対話性を処理しますが、レイアウトの残りの部分はサーバーでレンダリングされ、パフォーマンスと対話性のバランスが取れます。
逆に、クライアント コンポーネント内でサーバー コンポーネントを使用するユースケースも考えられます。その方法を確認してみましょう。
サーバー コンポーネントはクライアント コンポーネント内にネストできますが、クライアント コンポーネントに直接インポートできないことを理解することが重要です。サーバー コンポーネントをクライアント コンポーネントに含めるには、2 つの間の境界が壊れないように、それを子またはプロップとして渡します。
サーバー コンポーネントが子としてクライアント コンポーネントに渡される実際の例を次に示します。
// app/components/Header.js export default function Header() { return ( <header> <h1>My Static Header</h1> </header> ); }
上記の例では:
このパターンでは、クライアント側の対話性を維持しながら、サーバー レンダリングの利点 (JavaScript の削減、パフォーマンスの向上) を利用できます。
認証プロバイダーや UI コンポーネントなどの多くのサードパーティ ライブラリは、クライアント コンポーネントでのみ使用できる React フックに依存しています。クライアント コンポーネント内にサードパーティ ライブラリをラップすることで、この制限を回避する方法は次のとおりです。
// app/components/PostList.js export default async function PostList() { const res = await fetch('https://jsonplaceholder.typicode.com/posts'); const posts = await res.json(); return ( <ul> {posts.slice(0, 5).map((post) => ( <li key={post.id}>{post.title}</li> ))} </ul> ); }
サードパーティの React-Slick カルーセルをクライアント コンポーネントでラップすることで、インタラクティブ性などのクライアント側の機能にアクセスしながら、サーバーでレンダリングされたページでそれを使用できます。
サーバーとクライアントのコンポーネント間でデータを受け渡す場合、props はシリアル化可能である必要があります (文字列、数値、ブール値など)。関数やクラスのインスタンスなどの複雑なオブジェクトは渡すことができません。
// app/components/SearchBar.js 'use client'; // This makes the component a client component import { useState } from 'react'; export default function SearchBar() { const [searchTerm, setSearchTerm] = useState(''); return ( <div> <input type="text" value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} placeholder="Search..." /> <p>Searching for: {searchTerm}</p> </div> ); }
UserCard クライアント コンポーネントは、サーバー コンポーネントから渡されたデータを動的にレンダリングしながら、すべてがシリアル化可能であることを保証し、サーバーとクライアントの境界を問題なく通過できるようになりました。
以上のことを踏まえて、ベスト プラクティスでこれを締めくくるのは興味深いでしょう。次に進みましょう:
サーバーとクライアントのコンポーネントを効果的に構成するためのヒントをいくつか紹介します。
デフォルトでサーバー コンポーネント: JavaScript の負荷を軽減し、パフォーマンスを向上させるために、静的コンテンツまたはデータ駆動型コンテンツには可能な限りサーバー コンポーネントを使用します。
対話性のためにクライアント コンポーネントを使用する: ユーザー対話またはブラウザー固有の API が必要な場合にのみ、クライアント コンポーネントを使用します。
クライアント コンポーネントをツリーの下に移動: クライアント コンポーネントをコンポーネント ツリーのできるだけ深くにプッシュします。これにより、より多くのアプリがサーバー上でレンダリングされるようになり、パフォーマンスが向上します。
サーバー コンポーネントを子として渡す: サーバー コンポーネントをクライアント コンポーネント内で使用する必要がある場合は、直接インポートするのではなく、子またはプロップとして渡します。
Next.js 13 を使用すると、サーバーとクライアントの両方でコンポーネントを柔軟にレンダリングできます。静的コンテンツにはサーバー コンポーネント、対話性にはクライアント コンポーネントをデフォルトとして使用し、この 2 つの境界を慎重に管理することで、高速かつ動的なアプリを構築できます。
サーバー コンポーネントをクライアント コンポーネントに渡し、それらを慎重に組み合わせるなど、ここにあるパターンと例に従うことで、Next.js 13 の機能を最大限に活用して、高パフォーマンスでインタラクティブな Web アプリケーションを作成できるようになります。
楽しくコーディングしてください
私はマイケルです。
以上がNext.js のサーバー コンポーネントとクライアント コンポーネントの使用時期と使用方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。