use:レンダー中にリソースを読み取る新しいAPI
useはPromiseやContextなどのリソースから値を読み取るための新しいAPIです。現時点では、useに指定できるリソースはPromiseかContextのいずれかです。Contextのほうが直感的なため、先にそちらから見ていきましょう。
useでContextを読み取る
ContextはReactで状態管理を行う仕組みの一つで、祖先コンポーネントで指定された値を、子孫コンポーネントで参照できるようにする機構です。典型的には「UI テーマ」など、広範囲に影響を与える変数で、propsで受け渡すと煩雑になる状態管理に使われます。ただしグローバル変数に近いものなので、乱用は禁物です。
これまで子孫コンポーネントでContextの値を読み取るには、useContextフックを使ってきましたが、これをuseで置き換えることができます。
// テーマコンテキスト
const ThemeContext = createContext("light");
// テーマを変更するコンポーネント
function ThemeChanger() {
const [theme, setTheme] = useState("light");
return (
<div>
<button onClick={() => setTheme((prev) => (prev === "light" ? "dark" : "light"))}>
テーマ変更
</button>
<ThemeContext value={theme}>
<ThemeDisplay />
</ThemeContext>
</div>
);
}
// テーマを使用するコンポーネント
function ThemeDisplay() {
// const theme = useContext(ThemeContext); // 従来の useContext を使った書き方 ... (1)
const theme = use(ThemeContext); // React 19~の use を使った書き方 ...(2)
return <p>テーマ: {theme}</p>;
}
function App() {
return <ThemeChanger />;
}
上の例ではuseContextを使った書き方((1))をuseを使った書き方((2))に置き換えています。いずれも同じように動作します。
フックであるuseContextは、必ずコンポーネントの直下で呼び出す必要があり、if文などに含めたり、早期リターンの後には書けませんでした。useはいわゆる「フック」ではなく、if文やループなどの中でも呼び出すことができます。
リスト4のように、useは早期リターンの後でも使えるため、記述の自由度が高くなります。このため、今後はuseを使うことが推奨されています。
// テーマを使用するコンポーネント
function ThemeDisplay() {
if (someCondition) {
return null; // 早期リターン
}
const theme = use(ThemeContext); // 早期リターン後は、useContextはNGだが、useならOK
return <p>テーマ: {theme}</p>;
}
なお、これまでContextでは<Context.Provider>を使って下層のコンポーネントに適用していましたが、React 19からは<Context>を直接指定するように変更されました。従来の<Context.Provider>は将来のバージョンで非推奨になる予定のため、注意が必要です。
const ThemeContext = React.createContext("light");
function App() {
return (
// <ThemeContext.Provider value="dark"> {/* React 18 までの書き方 */}
// <ThemeDisplay />
// </ThemeContext.Provider>
<ThemeContext value="dark"> {/* React 19 以降の書き方 */}
<ThemeDisplay />
</ThemeContext>
);
}
useでPromiseの値を読み取る
もう一つのuseの用法が、Promiseを渡して、その結果を読み取ることです。「awaitすればいいのでは?」と思われるかもしれませんが、通常の関数コンポーネントは同期関数のため、直接的にawaitは使用できません。useの導入により、関数コンポーネント内でPromiseから結果を取り出せるようになります。
useはReact 18から導入されたSuspenseの仕組みを前提としており、渡されたPromiseが未解決の間、useはSuspendします。つまり、このuseを有効に使うためには、コンポーネントの上層でSuspenseが存在しなければなりません。
import { use, Suspense } from "react";
function DataDisplay({ dataPromise }) {
// useを使ってPromiseからデータを取り出す
// ※Promiseが未解決の間は中断されてSuspenseのフォールバックが表示される
const dataContent = use(dataPromise);
return <p>データ: {dataContent}</p>;
}
export function DataContainer({ dataPromise }) {
return (
// Promiseが未解決の間はフォールバックが表示される
<Suspense fallback={<p>読み込み中...</p>}>
<DataDisplay dataPromise={dataPromise} />
</Suspense>
);
}
まとめ
今回はReact 19の新しいAPIについて紹介しました。前回のuseActionStateフックや<form>アクションに加え、useOptimisticやuseFormStatusフック、useといった新しく便利なAPIが追加されていました。
次回はReact 19で正式にサポートされたReact Server Componentsやその他の変更点について紹介していくので、ご期待ください。
