use は Hook ではなく React API です。Promise の結果または Context の値をコンポーネントで読みます。Promise が未解決なら最も近い Suspense 境界を表示し、失敗は Error Boundary へ委ねます。
Promise を Suspense と組み合わせる
Promise はコンポーネントの外側、または Server Component から渡されたものを使います。
import { Suspense, use } from 'react';
function UserName({ userPromise }: { userPromise: Promise<{ name: string }> }) {
const user = use(userPromise);
return <p>{user.name}</p>;
}
function Profile({ userPromise }: { userPromise: Promise<{ name: string }> }) {
return <Suspense fallback={<p>読み込み中…</p>}><UserName userPromise={userPromise} /></Suspense>;
}
UserName の use(userPromise) が未解決の Promise に到達すると、React はそのコンポーネントの描画を中断し、近い Suspense の fallback を表示します。Promise が解決すると React は UserName をもう一度描画し、今度は解決値を返します。この待機の仕組みをコンポーネント自身が loading state で実装する必要はありません。
クライアントコンポーネントのレンダー中に毎回 fetch() して Promise を渡すと、毎回新しい Promise ができて無限に待機する原因になります。Promise の生成場所とキャッシュ方針を明確にします。
Suspense は Promise を待つあいだの表示を担当します。画面のどこまでを fallback に置き換えるかはユーザー体験の設計です。プロフィール全体を待たせるのか、名前だけに小さな fallback を置くのかを、データの独立性とレイアウトの安定性から選びます。
Hooks との違い
use は条件分岐やループ内で呼べます。ただし try / catch 内では呼べません。Context を読むこともできますが、通常は読みやすさのため useContext を使います。
Promise が reject したときは、use の周囲で try / catch するのではなく Error Boundary で失敗 UI を表示します。待機状態は Suspense、失敗状態は Error Boundary、成功時の画面はコンポーネントという三つの責務を分けると、非同期 UI を保守しやすくなります。
Context を読む use
use(SomeContext) でも Context の値を読め、条件分岐の中でしか必要にならない場合に利用できます。ただし、通常の読み取りは useContext(SomeContext) の方が意図を伝えやすく、Hooks の規則にも沿った一貫した書き方です。use の柔軟さを、複雑な条件分岐を増やす理由にはしません。
Promise の所有者を決める
Promise をどこで作り、誰がキャッシュし、いつ再取得するかは use とは別の責務です。フレームワークのデータ取得機構、Server Component、対応するキャッシュライブラリを利用し、コンポーネントは渡されたリソースを読む役に留めます。これにより waterfall、重複リクエスト、レンダーごとの Promise 再生成を避けられます。
まとめ
use は非同期リソースを React の Suspense と接続する API です。待機 UI とエラー UI を境界として設計し、Promise の生成をレンダーから切り離します。