React v19

2024年12月5日 Reactチーム


注記

React 19が安定版になりました!

この投稿が4月にReact 19 RCで最初に共有されてからの追加点

この投稿の日付は、安定版リリース日を反映するように更新されました。

React v19がnpmで利用可能になりました!

React 19アップグレードガイドでは、アプリをReact 19にアップグレードするためのステップバイステップの手順を共有しました。この投稿では、React 19の新機能の概要と、それらを導入する方法について説明します。

破壊的な変更のリストについては、アップグレードガイドを参照してください。


React 19の新機能

アクション

Reactアプリの一般的なユースケースは、データ変更を実行し、それに応答して状態を更新することです。たとえば、ユーザーが名前を変更するフォームを送信すると、APIリクエストを行い、その後レスポンスを処理します。これまで、保留中の状態、エラー、楽観的な更新、およびシーケンシャルリクエストを手動で処理する必要がありました。

たとえば、useStateで保留中とエラーの状態を処理できます

// Before Actions
function UpdateName({}) {
const [name, setName] = useState("");
const [error, setError] = useState(null);
const [isPending, setIsPending] = useState(false);

const handleSubmit = async () => {
setIsPending(true);
const error = await updateName(name);
setIsPending(false);
if (error) {
setError(error);
return;
}
redirect("/path");
};

return (
<div>
<input value={name} onChange={(event) => setName(event.target.value)} />
<button onClick={handleSubmit} disabled={isPending}>
Update
</button>
{error && <p>{error}</p>}
</div>
);
}

React 19では、保留中の状態、エラー、フォーム、および楽観的な更新を自動的に処理するために、トランジションで非同期関数を使用するためのサポートを追加しています。

たとえば、useTransitionを使用して、保留中の状態を処理できます

// Using pending state from Actions
function UpdateName({}) {
const [name, setName] = useState("");
const [error, setError] = useState(null);
const [isPending, startTransition] = useTransition();

const handleSubmit = () => {
startTransition(async () => {
const error = await updateName(name);
if (error) {
setError(error);
return;
}
redirect("/path");
})
};

return (
<div>
<input value={name} onChange={(event) => setName(event.target.value)} />
<button onClick={handleSubmit} disabled={isPending}>
Update
</button>
{error && <p>{error}</p>}
</div>
);
}

非同期トランジションは、すぐにisPending状態をtrueに設定し、非同期リクエストを行い、トランジション後にisPendingをfalseに切り替えます。これにより、データが変更されている間も、現在のUIを応答性とインタラクティブに保つことができます。

注記

慣例として、非同期トランジションを使用する関数は「アクション」と呼ばれます。

アクションは、データの送信を自動的に管理します

  • 保留中の状態:アクションは、リクエストの開始時に開始し、最終的な状態更新がコミットされると自動的にリセットされる保留中の状態を提供します。
  • 楽観的な更新:アクションは、新しいuseOptimisticフックをサポートしているため、リクエストの送信中にユーザーに即座にフィードバックを表示できます。
  • エラー処理:アクションはエラー処理を提供するため、リクエストが失敗した場合にエラー境界を表示し、楽観的な更新を元の値に自動的に戻すことができます。
  • フォーム<form>要素は、actionおよびformActionプロパティに関数を渡すことをサポートするようになりました。actionプロパティに関数を渡すと、デフォルトでアクションが使用され、送信後にフォームが自動的にリセットされます。

React 19では、Actionsをベースに、オプティミスティックな更新を管理するためのuseOptimisticという新しいフックと、Actionsの一般的なケースを処理するための新しいフックReact.useActionStateが導入されました。react-domでは、フォームを自動的に管理するための<form> Actionsと、フォームでのActionsの一般的なケースをサポートするためのuseFormStatusという新しいフックが追加されています。

React 19では、上記の例は以下のように簡略化できます。

// Using <form> Actions and useActionState
function ChangeName({ name, setName }) {
const [error, submitAction, isPending] = useActionState(
async (previousState, formData) => {
const error = await updateName(formData.get("name"));
if (error) {
return error;
}
redirect("/path");
return null;
},
null,
);

return (
<form action={submitAction}>
<input type="text" name="name" />
<button type="submit" disabled={isPending}>Update</button>
{error && <p>{error}</p>}
</form>
);
}

次のセクションでは、React 19の新しいAction機能についてそれぞれ詳しく見ていきましょう。

新しいフック: useActionState

Actionsの一般的なケースを簡単にするために、useActionStateという新しいフックを追加しました。

const [error, submitAction, isPending] = useActionState(
async (previousState, newName) => {
const error = await updateName(newName);
if (error) {
// You can return any result of the action.
// Here, we return only the error.
return error;
}

// handle success
return null;
},
null,
);

useActionStateは、関数(「Action」)を受け取り、呼び出すためのラップされたActionを返します。これは、Actionsが合成されるためです。ラップされたActionが呼び出されると、useActionStateは、Actionの最後の結果をdataとして、Actionの保留状態をpendingとして返します。

注記

React.useActionStateは、以前はCanaryリリースでReactDOM.useFormStateと呼ばれていましたが、名前が変更され、useFormStateは非推奨になりました。

詳細については、#28491を参照してください。

詳細については、useActionStateのドキュメントを参照してください。

React DOM: <form> Actions

Actionsは、react-domのReact 19の新しい<form>機能とも統合されています。<form><input>、および<button>要素のactionおよびformActionプロパティに関数を渡すことで、Actionsでフォームを自動的に送信できるようにサポートを追加しました。

<form action={actionFunction}>

<form> Actionが成功すると、Reactは自動的に非制御コンポーネントのフォームをリセットします。<form>を手動でリセットする必要がある場合は、新しいrequestFormReset React DOM APIを呼び出すことができます。

詳細については、react-domドキュメントの<form><input>、および<button>を参照してください。

React DOM: 新しいフック: useFormStatus

デザインシステムでは、コンポーネントにpropsを渡すことなく、コンポーネントが存在する<form>に関する情報にアクセスする必要があるデザインコンポーネントを作成するのが一般的です。これはContextを通じて行うことができますが、一般的なケースをより簡単にするために、新しいフックuseFormStatusを追加しました。

import {useFormStatus} from 'react-dom';

function DesignButton() {
const {pending} = useFormStatus();
return <button type="submit" disabled={pending} />
}

useFormStatusは、フォームがContextプロバイダーであるかのように、親の<form>のステータスを読み取ります。

詳細については、react-domドキュメントのuseFormStatusを参照してください。

新しいフック: useOptimistic

データ変更を実行する際のもう1つの一般的なUIパターンは、非同期リクエストが進行中に最終状態を楽観的に表示することです。React 19では、これを簡単にするためにuseOptimisticという新しいフックを追加しています。

function ChangeName({currentName, onUpdateName}) {
const [optimisticName, setOptimisticName] = useOptimistic(currentName);

const submitAction = async formData => {
const newName = formData.get("name");
setOptimisticName(newName);
const updatedName = await updateName(newName);
onUpdateName(updatedName);
};

return (
<form action={submitAction}>
<p>Your name is: {optimisticName}</p>
<p>
<label>Change Name:</label>
<input
type="text"
name="name"
disabled={currentName !== optimisticName}
/>
</p>
</form>
);
}

useOptimisticフックは、updateNameリクエストが進行中の間、すぐにoptimisticNameをレンダリングします。更新が完了またはエラーが発生した場合、Reactは自動的にcurrentName値に戻ります。

詳細については、useOptimisticのドキュメントを参照してください。

新しいAPI: use

React 19 では、レンダー内でリソースを読み込むための新しいAPIとして use を導入します。

例えば、use を使ってPromiseを読み込むことができます。ReactはPromiseが解決されるまでサスペンドします。

import {use} from 'react';

function Comments({commentsPromise}) {
// `use` will suspend until the promise resolves.
const comments = use(commentsPromise);
return comments.map(comment => <p key={comment.id}>{comment}</p>);
}

function Page({commentsPromise}) {
// When `use` suspends in Comments,
// this Suspense boundary will be shown.
return (
<Suspense fallback={<div>Loading...</div>}>
<Comments commentsPromise={commentsPromise} />
</Suspense>
)
}

注記

use は、レンダー内で作成されたPromiseをサポートしません。

レンダー内で作成されたPromiseを use に渡そうとすると、Reactは警告を発します。

コンソール
コンポーネントがキャッシュされていないPromiseによって中断されました。クライアントコンポーネントまたはフック内でのPromiseの作成は、Suspense対応のライブラリまたはフレームワークを介する場合を除き、まだサポートされていません。

これを修正するには、PromiseのキャッシュをサポートするSuspense対応のライブラリまたはフレームワークからのPromiseを渡す必要があります。将来的には、レンダー内でPromiseをキャッシュしやすくする機能をリリースする予定です。

また、use を使ってContextを読み込むこともできます。これにより、早期リターンの後など、条件付きでContextを読み込むことが可能になります。

import {use} from 'react';
import ThemeContext from './ThemeContext'

function Heading({children}) {
if (children == null) {
return null;
}

// This would not work with useContext
// because of the early return.
const theme = use(ThemeContext);
return (
<h1 style={{color: theme.color}}>
{children}
</h1>
);
}

use APIは、フックと同様に、レンダー内でのみ呼び出すことができます。フックとは異なり、use は条件付きで呼び出すことができます。将来的には、use を使ってレンダー内でより多くのリソースを消費できるようにする予定です。

詳細については、useのドキュメントを参照してください。

新しいReact DOMの静的API

静的サイト生成のために、react-dom/static に2つの新しいAPIを追加しました。

これらの新しいAPIは、静的HTML生成のためにデータの読み込みを待機することで、renderToString を改善します。これらは、Node.js StreamsやWeb Streamsのようなストリーミング環境で動作するように設計されています。例えば、Web Stream環境では、prerender を使ってReactツリーを静的HTMLにプリレンダリングできます。

import { prerender } from 'react-dom/static';

async function handler(request) {
const {prelude} = await prerender(<App />, {
bootstrapScripts: ['/main.js']
});
return new Response(prelude, {
headers: { 'content-type': 'text/html' },
});
}

プリレンダリングAPIは、すべてのデータの読み込みが完了するまで待ってから、静的HTMLストリームを返します。ストリームは文字列に変換したり、ストリーミングレスポンスで送信したりできます。これらは、既存のReact DOMサーバーレンダリングAPIでサポートされている、読み込み中のコンテンツのストリーミングをサポートしていません。

詳細については、React DOM静的APIを参照してください。

Reactサーバーコンポーネント

サーバーコンポーネント

サーバーコンポーネントは、クライアントアプリケーションやSSRサーバーとは別の環境で、バンドルする前にコンポーネントを事前にレンダリングできる新しいオプションです。この分離された環境がReactサーバーコンポーネントの「サーバー」です。サーバーコンポーネントは、CIサーバーでビルド時に一度実行することも、Webサーバーを使ってリクエストごとに実行することもできます。

React 19には、Canaryチャネルに含まれていたすべてのReactサーバーコンポーネントの機能が含まれています。つまり、サーバーコンポーネントを同梱するライブラリは、react-server export conditionを使って、フルスタックReactアーキテクチャをサポートするフレームワークで使用するために、React 19をピア依存関係としてターゲットにできるようになりました。

注記

サーバーコンポーネントのサポートを構築するにはどうすればよいですか?

React 19のReactサーバーコンポーネントは安定しており、メジャーバージョン間で破壊されることはありませんが、Reactサーバーコンポーネントのバンドラーまたはフレームワークを実装するために使用される基盤となるAPIは、セマンティックバージョニングに従っておらず、React 19.xのマイナーバージョン間で破壊される可能性があります。

バンドラーまたはフレームワークとしてReactサーバーコンポーネントをサポートするには、特定のReactバージョンに固定するか、Canaryリリースを使用することをお勧めします。今後も、Reactサーバーコンポーネントを実装するために使用されるAPIを安定させるために、バンドラーやフレームワークと協力していきます。

詳細については、Reactサーバーコンポーネントのドキュメントを参照してください。

サーバーアクション

サーバーアクションを使用すると、クライアントコンポーネントはサーバー上で実行される非同期関数を呼び出すことができます。

Server Action が "use server" ディレクティブで定義されている場合、フレームワークはサーバー関数への参照を自動的に作成し、その参照をクライアントコンポーネントに渡します。クライアントでその関数が呼び出されると、React は関数を実行するためにサーバーにリクエストを送信し、その結果を返します。

注記

Server Components にはディレクティブはありません。

よくある誤解は、Server Components が "use server" で示されるということですが、Server Components にはディレクティブはありません。"use server" ディレクティブは、Server Actions に使用されます。

詳細については、ディレクティブのドキュメントを参照してください。

Server Actions は Server Components で作成し、props として Client Components に渡すことも、Client Components でインポートして使用することもできます。

詳細については、React Server Actionsのドキュメントを参照してください。

React 19 での改善点

prop としての ref

React 19 から、関数コンポーネントの prop として ref にアクセスできるようになりました。

function MyInput({placeholder, ref}) {
return <input placeholder={placeholder} ref={ref} />
}

//...
<MyInput ref={ref} />

新しい関数コンポーネントでは forwardRef が不要になり、新しい ref prop を使用するようにコンポーネントを自動的に更新する codemod を公開する予定です。今後のバージョンでは、forwardRef を非推奨にし、削除する予定です。

注記

クラスに渡された refs は、コンポーネントインスタンスを参照するため、props としては渡されません。

ハイドレーションエラーの差分

react-dom のハイドレーションエラーに関するエラー報告も改善しました。たとえば、不一致に関する情報なしに、DEV で複数のエラーをログに記録するのではなく、

コンソール
警告: テキストコンテンツが一致しません。サーバー: “Server” クライアント: “Client” at span at App
警告: ハイドレーション中にエラーが発生しました。サーバーの HTML が <div> 内のクライアントコンテンツに置き換えられました。
警告: テキストコンテンツが一致しません。サーバー: “Server” クライアント: “Client” at span at App
警告: ハイドレーション中にエラーが発生しました。サーバーの HTML が <div> 内のクライアントコンテンツに置き換えられました。
捕捉されないエラー: テキストコンテンツがサーバーでレンダリングされた HTML と一致しません。 at checkForUnmatchedText ...

不一致の差分を含む単一のメッセージをログに記録するようになりました。

コンソール
捕捉されないエラー: サーバーでレンダリングされた HTML がクライアントと一致しなかったため、ハイドレーションに失敗しました。その結果、このツリーはクライアントで再生成されます。これは、SSR されたクライアントコンポーネントが使用した場合に発生する可能性があります。 - サーバー/クライアント分岐 if (typeof window !== 'undefined')。- Date.now()Math.random() のように、呼び出されるたびに変化する変数入力。- サーバーと一致しないユーザーのロケールでの日付書式設定。- HTML とともにスナップショットを送信せずに外部データが変化した場合。- 無効な HTML タグのネスト。 また、React がロードされる前に HTML を混乱させるブラウザ拡張機能がクライアントにインストールされている場合にも発生する可能性があります。 https://react.dokyumento.jp/link/hydration-mismatch <App> <span>+ クライアント- サーバー at throwOnHydrationMismatch ...

プロバイダーとしての <Context>

React 19 では、<Context.Provider> の代わりにプロバイダーとして <Context> をレンダリングできます。

const ThemeContext = createContext('');

function App({children}) {
return (
<ThemeContext value="dark">
{children}
</ThemeContext>
);
}

新しい Context プロバイダーは <Context> を使用でき、既存のプロバイダーを変換するための codemod を公開する予定です。今後のバージョンでは、<Context.Provider> を非推奨にする予定です。

refs のクリーンアップ関数

ref コールバックからクリーンアップ関数を返すことができるようになりました。

<input
ref={(ref) => {
// ref created

// NEW: return a cleanup function to reset
// the ref when element is removed from DOM.
return () => {
// ref cleanup
};
}}
/>

コンポーネントがアンマウントされると、React は ref コールバックから返されたクリーンアップ関数を呼び出します。これは、DOM refs、クラスコンポーネントへの refs、および useImperativeHandle で機能します。

注記

以前のReactでは、コンポーネントがアンマウントされる際に、ref関数をnullで呼び出していました。refがクリーンアップ関数を返す場合、Reactはこのステップをスキップするようになります。

将来のバージョンでは、コンポーネントのアンマウント時にnullでrefを呼び出すことを非推奨とする予定です。

refクリーンアップ関数の導入により、refコールバックから何か他のものを返すことはTypeScriptによって拒否されるようになります。修正方法は通常、暗黙的な戻り値の使用を止めることです。例えば、以下のようになります。

- <div ref={current => (instance = current)} />
+ <div ref={current => {instance = current}} />

元のコードではHTMLDivElementのインスタンスを返しており、TypeScriptはこれがクリーンアップ関数であるべきか、クリーンアップ関数を返したくなかったのかを判断できませんでした。

このパターンは、no-implicit-ref-callback-returnを使用してコードモッドできます。

useDeferredValueの初期値

useDeferredValueinitialValueオプションを追加しました。

function Search({deferredValue}) {
// On initial render the value is ''.
// Then a re-render is scheduled with the deferredValue.
const value = useDeferredValue(deferredValue, '');

return (
<Results query={value} />
);
}

initialValueが指定された場合、useDeferredValueはコンポーネントの最初のレンダリング時にそれをvalueとして返し、バックグラウンドでdeferredValueが返された状態で再レンダリングをスケジュールします。

詳細については、useDeferredValueを参照してください。

ドキュメントメタデータのサポート

HTMLでは、<title><link><meta>のようなドキュメントメタデータタグは、ドキュメントの<head>セクションに配置することが予約されています。Reactでは、アプリに適したメタデータを決定するコンポーネントが、<head>をレンダリングする場所から非常に離れている場合や、Reactが<head>をまったくレンダリングしない場合があります。過去には、これらの要素はエフェクトで手動で挿入するか、react-helmetのようなライブラリによって挿入する必要があり、Reactアプリケーションをサーバーレンダリングする際には注意深い処理が必要でした。

React 19では、コンポーネントでドキュメントメタデータタグをネイティブにレンダリングするサポートを追加しています。

function BlogPost({post}) {
return (
<article>
<h1>{post.title}</h1>
<title>{post.title}</title>
<meta name="author" content="Josh" />
<link rel="author" href="https://twitter.com/joshcstory/" />
<meta name="keywords" content={post.keywords} />
<p>
Eee equals em-see-squared...
</p>
</article>
);
}

Reactがこのコンポーネントをレンダリングすると、<title><link><meta>タグを認識し、それらを自動的にドキュメントの<head>セクションに持ち上げます。これらのメタデータタグをネイティブにサポートすることで、クライアントのみのアプリ、ストリーミングSSR、およびサーバーコンポーネントで動作することを保証できます。

注記

メタデータライブラリが必要な場合もあります

単純なユースケースでは、ドキュメントメタデータをタグとしてレンダリングするのが適切かもしれませんが、ライブラリは、現在のルートに基づいて一般的なメタデータを特定のメタデータで上書きするなど、より強力な機能を提供できます。これらの機能により、react-helmetのようなフレームワークやライブラリが、メタデータタグを置き換えるのではなく、サポートすることが容易になります。

詳細については、<title><link>、および<meta>のドキュメントを参照してください。

スタイルシートのサポート

外部リンク(<link rel="stylesheet" href="...">)とインライン(<style>...</style>)の両方のスタイルシートは、スタイルの優先順位のルールにより、DOM内の位置を慎重に配置する必要があります。コンポーネント内でコンポーザビリティを可能にするスタイルシート機能を構築するのは難しいため、ユーザーは、依存する可能性のあるコンポーネントから遠く離れた場所ですべてのスタイルをロードするか、この複雑さをカプセル化するスタイルライブラリを使用することがよくあります。

React 19では、この複雑さに対処し、クライアントでの同時レンダリングとサーバーでのストリーミングレンダリングへのさらに深い統合を、スタイルシートの組み込みサポートによって実現します。Reactにスタイルシートのprecedenceを伝えると、DOMでのスタイルシートの挿入順序を管理し、スタイルシート(外部の場合)がそれらのスタイルルールに依存するコンテンツを表示する前にロードされるようにします。

function ComponentOne() {
return (
<Suspense fallback="loading...">
<link rel="stylesheet" href="foo" precedence="default" />
<link rel="stylesheet" href="bar" precedence="high" />
<article class="foo-class bar-class">
{...}
</article>
</Suspense>
)
}

function ComponentTwo() {
return (
<div>
<p>{...}</p>
<link rel="stylesheet" href="baz" precedence="default" /> <-- will be inserted between foo & bar
</div>
)
}

サーバーサイドレンダリング中、Reactはスタイルシートを<head>に含め、ブラウザがロードするまで描画されないようにします。ストリーミングを開始した後にスタイルシートが遅れて検出された場合、Reactは、そのスタイルシートに依存するSuspense境界のコンテンツを表示する前に、スタイルシートがクライアントの<head>に挿入されるようにします。

クライアントサイドレンダリング中、Reactは、新しくレンダリングされたスタイルシートがロードされるまで、レンダリングのコミットを待ちます。アプリケーション内の複数の場所からこのコンポーネントをレンダリングすると、Reactはスタイルシートをドキュメントに1回だけ含めます。

function App() {
return <>
<ComponentOne />
...
<ComponentOne /> // won't lead to a duplicate stylesheet link in the DOM
</>
}

スタイルシートを手動でロードすることに慣れているユーザーにとって、これは、依存するコンポーネントの近くにスタイルシートを配置する機会であり、より良いローカルな推論を可能にし、実際に依存するスタイルシートのみをロードすることを容易にします。

スタイルライブラリやバンドラーとのスタイル統合もこの新しい機能を採用できるため、自分でスタイルシートを直接レンダリングしなくても、ツールがこの機能を活用するようにアップグレードされれば恩恵を受けることができます。

詳細については、<link><style> のドキュメントをご覧ください。

非同期スクリプトのサポート

HTMLでは、通常のスクリプト(<script src="...">)と遅延スクリプト(<script defer="" src="...">)はドキュメントの順序でロードされるため、このようなスクリプトをコンポーネントツリーの奥深くでレンダリングすることは困難です。しかし、非同期スクリプト(<script async="" src="...">)は任意の順序でロードされます。

React 19では、非同期スクリプトをコンポーネントツリーのどこにでも、スクリプトに実際に依存するコンポーネントの内側にレンダリングできるようにすることで、非同期スクリプトのサポートを改善しました。スクリプトインスタンスの再配置や重複排除を管理する必要はありません。

function MyComponent() {
return (
<div>
<script async={true} src="..." />
Hello World
</div>
)
}

function App() {
<html>
<body>
<MyComponent>
...
<MyComponent> // won't lead to duplicate script in the DOM
</body>
</html>
}

すべてのレンダリング環境で、非同期スクリプトは重複排除されるため、複数の異なるコンポーネントによってレンダリングされた場合でも、Reactはスクリプトを一度だけロードして実行します。

サーバーサイドレンダリングでは、非同期スクリプトは<head>に含まれ、スタイルシート、フォント、画像プリロードなどのペイントをブロックするより重要なリソースの後ろに優先順位が付けられます。

詳細については、<script>のドキュメントをご覧ください。

リソースのプリロードのサポート

ドキュメントの初期ロード時およびクライアント側の更新時に、ブラウザーにロードが必要になる可能性が高いリソースをできるだけ早く通知すると、ページのパフォーマンスに劇的な影響を与える可能性があります。

React 19には、ブラウザーリソースをロードおよびプリロードするための新しいAPIが多数含まれており、非効率なリソースロードによって阻害されない優れたエクスペリエンスを可能な限り簡単に構築できるようにします。

import { prefetchDNS, preconnect, preload, preinit } from 'react-dom'
function MyComponent() {
preinit('https://.../path/to/some/script.js', {as: 'script' }) // loads and executes this script eagerly
preload('https://.../path/to/font.woff', { as: 'font' }) // preloads this font
preload('https://.../path/to/stylesheet.css', { as: 'style' }) // preloads this stylesheet
prefetchDNS('https://...') // when you may not actually request anything from this host
preconnect('https://...') // when you will request something but aren't sure what
}
<!-- the above would result in the following DOM/HTML -->
<html>
<head>
<!-- links/scripts are prioritized by their utility to early loading, not call order -->
<link rel="prefetch-dns" href="https://...">
<link rel="preconnect" href="https://...">
<link rel="preload" as="font" href="https://.../path/to/font.woff">
<link rel="preload" as="style" href="https://.../path/to/stylesheet.css">
<script async="" src="https://.../path/to/some/script.js"></script>
</head>
<body>
...
</body>
</html>

これらのAPIを使用すると、スタイルシートのロードからフォントなどの追加リソースの検出を移動することで、初期ページロードを最適化できます。また、予想されるナビゲーションで使用されるリソースのリストをプリフェッチし、クリック時またはマウスオーバー時にこれらのリソースを積極的にプリロードすることで、クライアントの更新を高速化できます。

詳細については、リソースプリロードAPIを参照してください。

サードパーティのスクリプトと拡張機能との互換性

サードパーティのスクリプトとブラウザ拡張機能を考慮して、ハイドレーションを改善しました。

ハイドレーション時、クライアントでレンダリングされる要素がサーバーからのHTMLで見つかった要素と一致しない場合、Reactはコンテンツを修正するためにクライアントの再レンダリングを強制します。以前は、サードパーティのスクリプトまたはブラウザ拡張機能によって要素が挿入された場合、不一致エラーとクライアントレンダリングがトリガーされていました。

React 19では、<head><body>内の予期しないタグはスキップされ、不一致エラーが回避されます。Reactが関連のないハイドレーションの不一致のためにドキュメント全体を再レンダリングする必要がある場合、サードパーティのスクリプトとブラウザ拡張機能によって挿入されたスタイルシートはそのまま残されます。

より良いエラー報告

React 19では、重複を削除し、キャッチされたエラーとキャッチされなかったエラーを処理するためのオプションを提供するために、エラー処理を改善しました。たとえば、エラー境界によってキャッチされたレンダリング中にエラーが発生した場合、以前のReactではエラーが2回スローされ(最初は元のエラーに対して、次に自動回復に失敗した後)、エラーが発生した場所に関する情報とともにconsole.errorが呼び出されていました。

これにより、キャッチされたエラーごとに3つのエラーが発生していました。

コンソール
Uncaught Error: hit at Throws at renderWithHooks ...
Uncaught Error: hit <-- 重複 at Throws at renderWithHooks ...
上記のエラーは、Throwsコンポーネントで発生しました at Throws at ErrorBoundary at App Reactは、提供されたエラー境界であるErrorBoundaryを使用して、このコンポーネントツリーを最初から再作成しようとします。

React 19では、すべてのエラー情報が含まれた単一のエラーをログに記録します

コンソール
Error: hit at Throws at renderWithHooks ... 上記のエラーは、Throwsコンポーネントで発生しました at Throws at ErrorBoundary at App Reactは、提供されたエラー境界であるErrorBoundaryを使用して、このコンポーネントツリーを最初から再作成しようとします。 at ErrorBoundary at App

さらに、onRecoverableErrorを補完するために、2つの新しいルートオプションを追加しました。

  • onCaughtError: Reactがエラー境界でエラーをキャッチしたときに呼び出されます。
  • onUncaughtError: エラーがスローされ、エラー境界でキャッチされなかった場合に呼び出されます。
  • onRecoverableError: エラーがスローされ、自動的に回復した場合に呼び出されます。

詳細と例については、createRoothydrateRootのドキュメントを参照してください。

カスタム要素のサポート

React 19では、カスタム要素が完全にサポートされ、Custom Elements Everywhereのすべてのテストに合格しています。

過去のバージョンでは、Reactでカスタム要素を使用することは困難でした。Reactが認識されないpropsをプロパティではなく属性として扱っていたためです。React 19では、クライアント側とSSRの両方で動作するプロパティのサポートが、以下の戦略で追加されました。

  • サーバーサイドレンダリング:カスタム要素に渡されるpropsは、その型がstringnumberのようなプリミティブ値であるか、値がtrueの場合、属性としてレンダリングされます。objectsymbolfunctionのような非プリミティブ型であるか、値がfalseのpropsは省略されます。
  • クライアントサイドレンダリング:カスタム要素のインスタンス上のプロパティと一致するpropsはプロパティとして割り当てられ、それ以外の場合は属性として割り当てられます。

Reactにおけるカスタム要素のサポートの設計と実装を推進してくれたJoey Arharに感謝します。

アップグレード方法

詳しい手順と、破壊的な変更点や注目すべき変更点の完全なリストについては、React 19 アップグレードガイドをご覧ください。

注:この投稿は元々2024年4月25日に公開されましたが、安定版リリースに伴い2024年12月5日に更新されました。