Reactの最新バージョンである「React 19」が2024年12月5日にリリースされた。 本記事では、React 19の新機能と改善点を詳しく解説していく。
Actions
フォーム送信やデータ操作後の状態管理がより簡単に行えるようになった。
従来のコード
従来は、useState
で進行中の状態 (pending)を個別に管理する必要があった。
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={(e) => setName(e.target.value)} />
<button onClick={handleSubmit} disabled={isPending}>更新</button>
{error && <p>{error}</p>}
</div>
);
}
React 19での改善例useTransition
を利用することで、状態管理が自動化される。
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={(e) => setName(e.target.value)} />
<button onClick={handleSubmit} disabled={isPending}>更新</button>
{error && <p>{error}</p>}
</div>
);
}
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,
);
form
React 19では、<form>
の新機能として、action
プロパティに関数を渡せるようになり、自動的にフォームを送信する「Actions」がサポートされた。
<form action={actionFunction}>
useFormStatus
<form>
の情報をコンポーネントに渡すためにContextを使うことがあるが、これを簡単にするために新しいフックuseFormStatus
が追加された。
useFormStatus
を使うと、親の<form>
の状態をContextプロバイダーのように取得できる。
import {useFormStatus} from 'react-dom';
function DesignButton() {
const {pending} = useFormStatus();
return <button type="submit" disabled={pending} />
}
useOptimistic
いいねボタンなどデータの変更時に、非同期リクエスト中でも最終状態を楽観的に表示する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>
);
}
use
React 19では、新しいAPIとしてuse
が導入された。use
を使うと、レンダー中にPromiseを読み込むことができ、Promiseが解決するまでReactは自動的にSuspendされる。
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>
)
}
prerender・prerenderToNodeStream
React 19では、静的サイト生成向けにreact-dom/static
に新しいAPIprerender
・prerenderToNodeStream
が追加された。
これらのAPIはrenderToString
を改善し、静的HTML生成時にデータのロードを待機する。Node.js StreamsやWeb Streamsなどのストリーミング環境で使用可能。
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' },
});
}
React Server Components
サーバー側で事前にコンポーネントをレンダリングできるReact Server Componentsが安定版として提供された。
Server Actions
クライアントコンポーネントからサーバー上の非同期関数を呼び出す機能であるServer Actionsが安定版として提供された。
refのプロパティ化
React 19では、関数コンポーネントでref
を直接プロパティとして渡せるようになった。これにより、従来のforwardRef
を使ったコードが不要になる。
function MyInput({ placeholder, ref }) {
return <input placeholder={placeholder} ref={ref} />;
}
<MyInput ref={ref} />;
Contextがプロバイダーとして使用可能に
React 19では、<Context.Provider>
の代わりに、直接<Context>
をプロバイダーとしてレンダリングできるようになった。
const ThemeContext = createContext('');
function App({children}) {
return (
<ThemeContext value="dark">
{children}
</ThemeContext>
);
}
refのクリーンアップ関数
Reactでは、ref
コールバックからクリーンアップ関数を返すことが可能になった。
<input
ref={(ref) => {
// ref が作成されたときの処理
// NEW: 要素がDOMから削除された際に
// ref をリセットするクリーンアップ関数を返す
return () => {
// ref のクリーンアップ処理
};
}}
/>
useDeferredValueの初期値 (initialValue) サポート
useDeferredValue
にinitialValue
オプションが追加された。
function Search({deferredValue}) {
// 初回レンダー時、valueは空文字列 ''。
// その後、バックグラウンドで deferredValue を使った再レンダーがスケジュールされる。
const value = useDeferredValue(deferredValue, '');
return (
<Results query={value} />
);
}
- 初期値 (
initialValue
) を指定可能。 - コンポーネントの初回レンダーでは
initialValue
を返し、バックグラウンドでdeferredValue
に基づく再レンダーをスケジュール。 - ユーザー体験の改善やパフォーマンス最適化に役立つ。
メタデータのネイティブサポート
React 19では、<title>
や<meta>
、<link>
などのドキュメントメタデータタグをコンポーネント内でネイティブに扱えるようになった。
Reactがこれらのタグを自動的に検出し、HTMLドキュメントの<head>
セクションに移動(hoist)する。
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 19のリリースにより、非同期処理の簡素化やサーバーサイドレンダリングの強化など、開発者にとって多くの利便性が向上した。 これらの新機能を活用することで、より高品質なユーザーインターフェースの構築が可能となる。 詳細やアップグレード手順については、公式のReact19アップグレードガイドをご参照ください。