React 19は、2024年12月にリリースされたReactのメジャーバージョンです。アクション(保留中の状態、エラー、フォームを管理するasync関数)、フック useActionState、useOptimistic、use、普通のpropとしての ref、そしてReactがドキュメントのheadに移動する <title> と <meta> タグが追加されました。React 19.2(2025年10月)では <Activity> と useEffectEvent が追加されました。
下のすべての例はReact 19.2で動きます。まずアクションです。フォームに渡したasync関数で、保留中の状態と返されたエラーは useActionState が扱います。
欄を空のままSaveを押してエラーを確認し、次に名前を入力して保存してください。ボタンは800ミリ秒の間「Saving...」と表示されます。エラーのための useState も、isLoading フラグも、e.preventDefault() もありません。
アクションとフォームアクション
React 18では、どのフォームでも同じ手順を書いていました。デフォルトの送信を防ぎ、読み込み中フラグを立て、リクエストをawaitし、エラーを保存し、フラグを下ろす、です。React 19は、トランジションの中で非同期の作業をする関数をアクションと呼び、その事務処理を代わりにやってくれます。
startTransition(とuseTransition)がasync関数を受け付けるようになりました。isPendingは関数全体が終わるまでtrueのままです。<form action={fn}>は、フォームが送信されたときにフォームのFormDataを渡してfnを呼びます。これはアクションとして実行され、終わるとReactがフォームの非制御の項目をリセットします。<button formAction={fn}>は、1つの送信ボタンに独自のアクションを与えます。- useActionStateはアクションが最後に返した値を保つので、アクションはエラーメッセージや保存したレコードを返せます。
react-domのuseFormStatusを使えば、フォームの中のコンポーネントが、propsを下へ渡さずにそのフォームが送信中かどうかを読めます。親の<form>が必要なので、ここでは静的なブロックで示します。
import { useFormStatus } from 'react-dom';
function SubmitButton() {
const { pending } = useFormStatus();
return <button disabled={pending}>{pending ? 'Sending...' : 'Send'}</button>;
}
useOptimistic
useOptimistic は、アクションの実行中に予想される結果を表示し、アクションが終わると本当のstateに戻ります。いいねのカウンターは、クリックした瞬間に増え、リクエストが失敗したら元に戻せます。
const [optimisticLikes, addOptimisticLike] = useOptimistic(likes, (current, delta) => current + delta);
useOptimisticのページには、わざと失敗する偽のAPIを使った動く例があり、ロールバックの様子を観察できます。
use API
use はPromiseやコンテキストから値を読みます。Promiseの場合は、Promiseが解決するまでコンポーネントをサスペンドさせ、その間は最も近い <Suspense> がフォールバックを表示します。ほかのすべてのフックと違い、use は if やループの中、そして早期 return の後でも呼べます。
React 19では、<ThemeContext.Provider> の代わりに <ThemeContext value="dark"> を直接描画することもできます。次の例ではその両方が登場します。
propとしてのrefと、refのクリーンアップ
関数コンポーネントは、ほかのpropと同じように ref を受け取るようになりました。refをDOM要素まで渡すために、forwardRef で包む必要はもうありません。
refコールバックはクリーンアップ関数を返すこともできます。エフェクトのクリーンアップと同じように、Reactは要素が画面から消えるときにそれを呼びます。何も返さないコールバックは、React 18と同じく、取り除かれるときに null を渡して呼ばれます。
ボタンを何回かクリックしてコンソールを読んでください。取り除くたびにクリーンアップの行が、戻すたびに attached to DIV が記録されます。
ドキュメントのメタデータ
<title>、<meta>、<link> をコンポーネントのどこに描画しても、Reactがそれを <head> に移動します。ページのコンポーネントは、react-helmetのようなライブラリなしで自分のタイトルを設定できます。
プレビューには表示するブラウザのタブがないので、代わりにエフェクトが document.title をログに出します。記事を切り替えると、記録されるタイトルもそれに続きます。
スタイルシートも同じ扱いになりました。コンポーネントの中の <link rel="stylesheet" href="..." precedence="default" /> は、precedenceの順にheadへ1回だけ挿入され、Reactはそれを必要とする中身を表示する前に読み込みを待ちます。複数のコンポーネントが描画する <script async src="..."> は1回だけ読み込まれます。react-dom は、リソースのヒントのために preload、preinit、preconnect、prefetchDNS もエクスポートしています。
ActivityとuseEffectEvent(React 19.2)
<Activity mode="hidden"> は、子のstateを捨てずに隠します。ReactはDOMを隠し、エフェクトのクリーンアップを実行し、モードが再び "visible" になるとすべてを元に戻します。ユーザーが戻ってくると予想されるタブやパネルに向いています。
メモを入力し、Aboutに切り替えてから戻ってください。テキストは残っていて、コンソールを見ると、隠れている間はエフェクトがクリーンアップされていたことがわかります。<Activity> の包みを {tab === 'notes' && <Notes />} に置き換えると、切り替えるたびにメモが失われます。
useEffectEvent は、関数をエフェクトの依存値から外します。その関数は常に最新のpropsとstateを見ますが、それらが変わってもエフェクトは再起動しません。
function ChatRoom({ roomId, theme }) {
const onConnected = useEffectEvent(() => {
showNotification('Connected!', theme);
});
useEffect(() => {
const connection = createConnection(roomId);
connection.on('connected', () => onConnected());
connection.connect();
return () => connection.disconnect();
}, [roomId]); // theme is not a dependency
}
19.2では、Server Components向けの cacheSignal(cache() の結果がもう不要になったことを教えます)と、Chrome DevToolsのパフォーマンスパネルのPerformance Tracksも追加されました。React 19.1では、現在のコンポーネントをどのコンポーネントが描画したかを返す、開発専用の関数 captureOwnerStack が追加されました。
Server ComponentsとServer Functions
Server Componentsは、サーバーで(またはビルド時に)事前に実行され、その出力をブラウザに送るコンポーネントです。async にでき、データベースを直接読め、そのコードはクライアントに送られません。Server Functions(最初はServer Actionsと呼ばれていました)は、'use server' を付けたasync関数で、クライアントコンポーネントから普通の関数のように呼べます。どちらも、Next.jsのApp Routerのように、それをサポートするバンドラーを持つフレームワークが必要なので、このエディタでは動かせません。
// A Server Component: async, runs on the server only
export default async function Notes() {
const notes = await db.notes.findMany();
return notes.map((note) => <Note key={note.id} note={note} />);
}
// A Server Function, usable as a form action
async function createNote(formData) {
'use server';
await db.notes.create({ text: formData.get('text') });
}
削除・変更されたAPI
React 19では、何年も前から非推奨だったAPIが削除されました。
| 削除されたもの | 代わりに使うもの |
|---|---|
ReactDOM.render、ReactDOM.hydrate | react-dom/client の createRoot、hydrateRoot |
unmountComponentAtNode | root.unmount() |
findDOMNode | DOM要素に付けたref |
文字列ref(ref="input") | useRef かrefコールバック |
レガシーコンテキスト(contextTypes、getChildContext) | static contextType か use と組み合わせた createContext |
propTypes のチェック(今は黙って無視される) | TypeScript、または自前のチェック |
関数コンポーネントの defaultProps | 引数のデフォルト値 |
react-dom/test-utils | react の act。それ以外はReact Testing Library |
react-test-renderer/shallow | react-shallow-renderer パッケージ |
React.createFactory | JSX |
クラスコンポーネントは defaultProps を使い続けられます。エラーの報告方法も変わりました。エラーバウンダリが捕まえたエラーは console.error で1回だけ記録され、捕まえられなかったエラーは window.reportError に送られ、createRoot は自分で報告するための onCaughtError と onUncaughtError オプションを受け付けます。
React 19へのアップグレード
まずReact 18.3にアップグレードしてください。18.2と同じものですが、非推奨のAPIや、React 19が必要とするほかの変更について警告するので、アプリが動いているうちに直せます。React 19は新しいJSX変換も必要としますが、Viteや現行のすべてのフレームワークはすでにそれを使っています。それからReact 19をインストールします。
npm install react@^19 react-dom@^19
npm install --save-dev @types/react@^19 @types/react-dom@^19
公式のアップグレードガイドは、機械的な変更のためのcodemodを案内しています。1つ目は文字列ref、act のインポート、ReactDOM.render を扱い、2つ目はTypeScriptのコードを新しい型に合わせて更新します。
npx codemod@latest react/19/migration-recipe
npx types-react-codemod@latest preset-19 ./src
アップグレードした後も、アクションや新しいフックの採用を強制されることはありません。既存のコンポーネント、フック、クラスコンポーネントは動き続けるので、フォームを1つずつ <form action> に移していけます。
よくある質問
React 19はいつリリースされましたか?
React 19は2024年12月に安定版になりました。その後、React 19.1が2025年3月に、React 19.2が2025年10月にリリースされました。
React 19の一番大きな変更点は何ですか?
アクション(保留中の状態、エラー、フォームを代わりに扱ってくれるasync関数)、フック useActionState、useOptimistic、use、普通のpropとしての ref、プロバイダーとしての <Context>、ドキュメントのheadに移動する <title> と <meta> タグです。Server Componentsはフレームワーク向けに安定版になりました。
React 19でforwardRefは非推奨ですか?
関数コンポーネントが ref を普通のpropとして受け取れるようになったので、新しいコードでは forwardRef は不要です。今も動き、Reactチームは将来のバージョンで非推奨にすると述べています。
React 19でReact 18のアプリは壊れますか?
壊れるとすれば、主に削除されたAPIによるものです:ReactDOM.render、findDOMNode、文字列ref、レガシーコンテキスト、propTypes、関数コンポーネントの defaultProps。React 19は新しいJSX変換も必要とします。まずReact 18.3にアップグレードして非推奨の警告を直し、それからReact 19のcodemodを実行してください。
React 19を使うにはNext.jsが必要ですか?
いいえ。アクション、新しいフック、propとしてのref、メタデータは、Viteで作った普通のクライアントアプリですべて動きます。Server ComponentsとServer Functionsには、Next.jsのようなそれをサポートするフレームワークが必要です。