---
title: "React 19.3の新機能｜ViewTransition・Fragment ref・browser()の実装と19.2からの更新手順"
url: "https://www.issoh.co.jp/tech/details/18249/"
published: 2026-10-11
updated: 2026-10-11
categories: ["開発"]
publisher: "株式会社一創"
---

# React 19.3の新機能｜ViewTransition・Fragment ref・browser()の実装と19.2からの更新手順

React 19.3は2026年9月9日に公開され、10月11日時点でnpmの`latest`タグは`19.3.0`を指しています。目玉は、2025年に実験的APIとして紹介された`<ViewTransition>`とFragment refが安定版になったことです。ほかにSSRでブラウザ専用の描画をクライアントへ回す`browser()`、Trusted Types対応、Server ComponentsからのContext直接描画が加わりました。この記事では[React公式ブログの19.3告知](https://react.dev/blog/2026/09/09/react-19-3)を正として、動かせるコード、19.2から上げるときに挙動が変わる箇所、新機能を入れない画面の条件をまとめました。19.2で入った`<Activity>`や`useEffectEvent`は[React 19.2の新機能｜Activity・useEffectEvent・cacheSignal・PPRの使い方](https://www.issoh.co.jp/tech/details/9427/)で扱っています。

## まとめ：React 19.3で安定版になった機能と19.2から上げる前の確認4点

- 19.3.0は2026年9月9日公開。10月11日時点でパッチ版（19.3.1）は出ていません。
- `<ViewTransition>`とFragment refが安定版になり、`addTransitionType`、`browser()`、Trusted Types対応、Server ComponentsでのContext直接描画が加わりました。
- 公式ブログに破壊的変更の記載はありません。ただしTransitionの並列描画、hydration時のStrict Modeの二重実行など、動きが変わる変更は入っています。
- `<ViewTransition>`はDOM専用です。React Nativeの画面には使えません。

## React 19.3のリリース日と追加機能の一覧・npmで入っている版を確かめる手順

### 2026年9月9日公開の19.3.0とnpmのlatestタグで確かめる版番号

npm registryの公開日時を見ると、`react`と`react-dom`の19.3.0はどちらも2026年9月9日の公開です。直前の19.2系は19.2.8（2026年7月21日）が最後で、型定義の`@types/react`も同じ日に19.3.0が出ています。手元のプロジェクトでどの版が解決されているかは、次のコマンドで確かめられます。

```
npm view react version
npm ls react react-dom
npm view react time --json
```

1行目はレジストリの最新版、2行目はプロジェクトに実際に入っている版です。`react`と`react-dom`の版がずれていると、`react-dom` 19.3.0は`react`の`^19.3.0`を要求するため依存解決で警告が出ます。公式の版一覧は[React Versions](https://react.dev/versions)にもまとまっています。

### 安定版になった2つの機能と新規APIの収録パッケージを比べる対応表

19.3の追加分を、どのパッケージに入ったかと合わせて整理すると次のとおりです。

| 機能                  | パッケージ        | 19.3での扱い        |
| ------------------- | ------------ | --------------- |
| `<ViewTransition>`  | react        | 実験版から安定版へ       |
| `addTransitionType` | react        | 遷移の向きを付ける       |
| Fragment ref        | react        | 実験版から安定版へ       |
| `browser()`         | react-dom    | 新規API           |
| Trusted Types対応     | react-dom    | 値を文字列化しない       |
| Context直接描画         | react-server | Providerの部品が不要に |

`browser()`は`react`ではなく`react-dom`から読み込む点に注意してください。

## ViewTransitionで要素の出現と消滅をアニメーションさせる実装手順

### startTransitionで包んだ更新だけが動くenterとexitの基本形

[<ViewTransition>](https://react.dev/reference/react/ViewTransition)は、ブラウザの[View Transition API](https://developer.mozilla.org/en-US/docs/Web/API/View%5FTransition%5FAPI)を使って、子要素の出現（enter）、消滅（exit）、内容の変化（update）、名前付き要素の移動（share）をアニメーションさせる部品です。

```
import { ViewTransition, useState, startTransition } from 'react';

export default function Panel() {
  const [open, setOpen] = useState(false);
  return (
    <>
      <button onClick={() => startTransition(() => setOpen(v => !v))}>
        {open ? '閉じる' : '開く'}
      </button>
      {open && (
        <ViewTransition>
          <section className="detail">詳細の内容</section>
        </ViewTransition>
      )}
    </>
  );
}
```

動くのは`startTransition`の中の更新、`<Suspense>`の表示切替、`useDeferredValue`による更新の3種類だけです。`onClick`の中で`setOpen`を直接呼ぶと、要素は即座に切り替わりアニメーションしません。既定の動きはクロスフェードで、入力への反応を優先する通常の更新を巻き込まない設計になっています。

### addTransitionTypeで次へと前への向きを分けるカルーセル実装

同じ`setState`でも、操作の理由で動きを変えたい場面があります。[addTransitionType](https://react.dev/reference/react/addTransitionType)はTransitionに種類の名前を付け、`enter`や`exit`のpropsで種類ごとにCSSクラスを割り当てます。

```
import { ViewTransition, addTransitionType, startTransition } from 'react';

function next() {
  startTransition(() => {
    addTransitionType('next');
    setIndex(i => i + 1);
  });
}

<ViewTransition
  key={slide.id}
  enter={{ next: 'from-right', previous: 'from-left' }}
  exit={{ next: 'to-left', previous: 'to-right' }}
>
  <Slide slide={slide} />
</ViewTransition>
```

`from-right`などはCSS側で定義するクラス名です。Reactは種類の名前をブラウザのview transition typeとしても付けるため、CSSの`:active-view-transition-type(next)`で範囲を絞った書き方もできます。`key`を変えて要素を差し替えることで、旧スライドのexitと新スライドのenterが同時に走ります。

### Suspenseのfallbackから本体への切替だけを動かす設定例

データ取得と組み合わせると、読み込み表示から本来の内容へ切り替わる瞬間をアニメーションにできます。公式ブログが勧める型は「fallbackは即表示、fallbackから本体への切替だけ動かす、取得済みなら動かさない」の3原則です。

```
<ViewTransition update="auto" default="none">
  <Suspense fallback={<CardSkeleton />}>
    <ProfileCard userId={id} />
  </Suspense>
</ViewTransition>
```

`default="none"`でenterとexitを止め、`update="auto"`で切替だけを残します。この指定を省くと、キャッシュ済みで一瞬で出る場面でもフェードが入るため、操作のたびに画面がもたつく印象になるのが難点です。Suspenseと`use`でデータを読む書き方そのものは、[Async Reactとは？Transition・Suspense・useOptimisticで非同期UIを組む実装](https://www.issoh.co.jp/tech/details/11005/)で詳しく扱っています。

### 動かないときに疑うDOM要素との配置順序とnameの重複エラー

「書いたのにアニメーションしない」の原因で最も多いのは置き場所です。リファレンスのトラブルシューティングによると、enterとexitが動くのは`<ViewTransition>`がDOM要素より外側にあるときだけです。`<div>`の内側に置くと発動しません。

もう1つは共有要素用の`name`です。同じ`name`の`<ViewTransition>`が同時にマウントされるとエラーになるため、一覧の各行に使うなら`` name={`item-${id}`} ``のようにIDを含めて一意にします。`prefers-reduced-motion`をReactは自動で無効化しないので、CSSの`@media (prefers-reduced-motion)`でアニメーションを止める指定は自分で書いてください。ブラウザごとのView Transitions APIの対応状況は[View Transitions APIの対応ブラウザと実装手順](https://www.issoh.co.jp/tech/details/2384/)で確認できます。

## Fragment refでラッパーのdivを足さずに複数の子要素を操作する方法

### FragmentInstanceが持つイベント・フォーカス・監視・計測の4系統

19.3から[<Fragment>](https://react.dev/reference/react/Fragment)に`ref`を渡せるようになり、`ref.current`には`FragmentInstance`が入ります。これまで複数の兄弟要素をまとめて監視するには、ref用の`<div>`を足すしかなく、FlexboxやGridのレイアウトが崩れる原因になっていました。

- イベント：`addEventListener`、`removeEventListener`、`dispatchEvent`（第1階層の子が対象）
- フォーカス：`focus`、`focusLast`、`blur`（入れ子の子を深さ優先でたどる）
- 監視：`observeUsing`、`unobserveUsing`（`IntersectionObserver`や`ResizeObserver`を接続）
- 計測：`getClientRects`、`getRootNode`、`compareDocumentPosition`、`scrollIntoView`

外部ライブラリの部品が`ref`を受け取らない場合でも、Fragmentで包めば外側から振る舞いを足せます。単一要素への`ref`の基本は[useRefの使い方｜DOM参照・値の保持とuseStateとの違い](https://www.issoh.co.jp/tech/details/3279/)を参照してください。

### IntersectionObserverを接続して表示状態を返すInView部品の実装例

子要素のどれか1つでも画面に入ったら`onChange(true)`を呼ぶ部品は、次のように書けます。公式ブログの例を、実務で使いやすい形に短くしたものです。

```
import { Fragment, useRef, useLayoutEffect } from 'react';

export function InView({ onChange, children }) {
  const ref = useRef(null);
  useLayoutEffect(() => {
    const visible = new Set();
    const observer = new IntersectionObserver(entries => {
      entries.forEach(e => e.isIntersecting ? visible.add(e.target) : visible.delete(e.target));
      onChange(visible.size > 0);
    });
    const fragment = ref.current;
    fragment.observeUsing(observer);
    return () => fragment.unobserveUsing(observer);
  }, [onChange]);
  return <Fragment ref={ref}>{children}</Fragment>;
}
```

後片付けで`unobserveUsing`を呼ばないと、部品が消えたあとも監視が残ります。`onChange`を親で毎回作り直すと購読も毎回やり直しになるため、親側で`useCallback`に包むか、React Compilerを入れている環境ならその自動メモ化に任せてください。

## browser()でSSR中にブラウザ専用の描画をクライアントへ回す書き方

### useEffectのmountedフラグを置き換えるuse(browser())の基本形

`localStorage`やブラウザのタイムゾーンに依存する部品は、サーバーで正しいHTMLを作れません。これまでは`useEffect`で`mounted`フラグを立てるか、`typeof window`で分岐していました。後者はサーバーとクライアントでHTMLが食い違い、[ハイドレーションエラー](https://www.issoh.co.jp/tech/details/3218/)の典型的な原因になります。

```
import { Suspense, use } from 'react';
import { browser } from 'react-dom';

function TimeZone() {
  use(browser());
  const tz = new Intl.DateTimeFormat().resolvedOptions().timeZone;
  return <p>{tz}</p>;
}

export default function App() {
  return (
    <Suspense fallback={<p>読み込み中…</p>}>
      <TimeZone />
    </Suspense>
  );
}
```

サーバーでは`use(browser())`がSuspenseを起こし、最寄りの境界のfallbackがHTMLに入ります。ブラウザではsuspendせずにそのまま描画が進みます。通常の`use`と同じく、条件分岐や早期returnの後でも呼べるので、「初期値が渡されていればサーバーで描き、無ければブラウザへ回す」という書き分けも可能です。`use`そのものの規則は[Reactのuseフック（use API）の使い方](https://www.issoh.co.jp/tech/details/2989/)にまとめています。

### Suspense境界が無いと失敗する制約とonBrowserBailoutでの記録

[browserのリファレンス](https://react.dev/reference/react-dom/browser)には、注意点が3つ書かれています。サーバー描画中は`<Suspense>`の内側で呼ぶこと（無いとサーバー描画が失敗する）、Client Componentから呼ぶこと、`browser()`を単独で呼んでも何も起きず`use`に渡す必要があること、の3点です。

どの部品がクライアントへ回されたかは、サーバー描画APIの`onBrowserBailout`で記録できます。`browser()`の引数に理由を渡すと、記録されるエラーの`cause`に入ります。

```
const { pipe, abort } = renderToPipeableStream(<App />, {
  onShellReady() {
    pipe(res);
    setTimeout(() => abort(browser('server render timed out')), 10000);
  },
  onBrowserBailout(error, errorInfo) {
    console.warn(error.cause, errorInfo.componentStack);
  },
});
```

`abort`に`browser()`の戻り値を渡すと、10秒で間に合わなかったSuspense境界をfallbackのまま送り、残りをブラウザで描かせられます。この経路では`onError`も`hydrateRoot`の`onRecoverableError`も呼ばれないため、監視を`onError`だけに頼っていると、クライアント描画へ落ちた件数が見えなくなります。

## Trusted Types対応とサーバー側のContext直接描画の実装変更

### CSP設定時にinnerHTMLへの型付きオブジェクト代入が通る理由

[Trusted Types](https://developer.mozilla.org/en-US/docs/Web/API/Trusted%5FTypes%5FAPI)は、DOMベースのXSSを防ぐブラウザの仕組みです。CSPの`require-trusted-types-for`で有効にすると、`innerHTML`などへ生の文字列を入れることが禁止され、ポリシーを通して作った`TrustedHTML`などの型付きオブジェクトだけが受け付けられます。仕様は[W3CのTrusted Types仕様](https://w3c.github.io/trusted-types/dist/spec/)にあります。

```
Content-Security-Policy: require-trusted-types-for 'script'; trusted-types app-html

const policy = trustedTypes.createPolicy('app-html', {
  createHTML: input => DOMPurify.sanitize(input),
});
<div dangerouslySetInnerHTML={{ __html: policy.createHTML(html) }} />
```

19.2までのReactは値を`'' + value`で文字列に戻していたため、せっかく作った`TrustedHTML`がただの文字列になり、ブラウザに拒否されていました。19.3は値を文字列化せずに渡すので、ポリシーが意図どおり効きます。XSS対策全体の考え方は[XSSとCSRFの違い｜仕組み・対策を実装レベルで比較](https://www.issoh.co.jp/tech/details/4109/)で整理しています。

### Server ComponentからのContext直接描画で省ける部品

Server ComponentはContextを作れませんが、19.3からは`'use client'`のファイルで作ったContextを読み込んで、そのまま描画できます。これまではContextを渡すためだけの`UserProvider`部品を別に書いていました。

```
// user-context.js
'use client';
import { createContext } from 'react';
export const UserContext = createContext(null);

// layout.js（Server Component）
import { UserContext } from './user-context';
export async function Layout({ children }) {
  const currentUser = await getCurrentUser();
  return <UserContext value={currentUser}>{children}</UserContext>;
}
```

ログイン利用者などをクライアント側へ配るためだけのContextで、部品が1つ減ります。Contextの基本は[React Contextの使い方](https://www.issoh.co.jp/tech/details/2681/)、サーバーとクライアントの境界の考え方は[React Server Components（RSC）とは？](https://www.issoh.co.jp/tech/details/4003/)を参照してください。

## 19.2から19.3へ上げるときに挙動が変わる変更点と更新コマンド

### npm installで上げるパッケージと@types/reactの版合わせ

`react`と`react-dom`は必ず同時に上げます。TypeScriptの環境では`@types/react`と`@types/react-dom`も19.3系へそろえないと、`<ViewTransition>`や`browser`の型が見つからずエラーになります。

```
npm install react react-dom
npm install -D @types/react @types/react-dom
npm ls react react-dom @types/react
```

最後の行で、すべてが19.3.0に解決されたことを確かめてください。`package.json`の範囲指定が`~19.2.0`のように固定されている場合は、範囲を書き換えてからパッケージを入れ直してください。Next.jsなどのフレームワーク経由で使っている場合は、フレームワーク側でどの版に対応しているか、対応版の告知も合わせて確認する必要があります。Next.jsの直近の変更は[Next.js 16.3とは？](https://www.issoh.co.jp/tech/details/15608/)にまとめています。

### Transitionの並列描画とSSR時のStrict Mode二重実行の影響

Changelogのうち、既存アプリの動きを変えうるのは次の2つです。

1つ目は[Transitionの並列描画（PR #37290）](https://github.com/react/react/pull/37290)です。これまで同時に進む複数のTransitionは1回の描画にまとめられていましたが、19.3では個別に描画されます。遅い画面遷移があっても、無関係な検索欄の絞り込みは、その画面遷移の完了を待つ必要がありません。その代わり、2つのTransitionの結果が同じ瞬間に画面へ出ることを前提にした実装は、間の状態が一瞬見える可能性があります。

2つ目は[hydration時のStrict Modeの二重実行（PR #35961）](https://github.com/react/react/pull/35961)です。SSRしたページでも、開発環境ではEffectが2回走るようになりました。クライアント描画のルートと同じ動きにそろえる変更で、本番の挙動は変わりません。ただし開発中に「SSRのページだけEffectが1回」を前提にしていたログ送信や計測コードは、19.3で重複して見えます。

### number入力のdefaultValueなど細かな挙動変更の確認先

小さな変更では、`type="number"`の入力欄の`defaultValue`の更新が他の入力型と同じ扱いになりました。フォームを再描画したときに初期値が書き換わるかどうかが変わるので、数値入力を多く持つ業務画面では一度動かして確かめてください。

ほかに、Server Actionによるフォームの自動リセットで`onReset`が発火する変更や、`useDeferredValue`が古い値のまま止まる不具合の修正が入りました。全件は公式ブログ末尾のChangelogで確認できます。

## React 19.3の新機能を本番に採用する条件と見送る画面の判断基準

### ViewTransitionを入れてよい画面と入れない画面の条件

ViewTransitionを入れてよいのは、一覧から詳細への遷移、タブやカルーセルの切替、Suspenseで遅れて出るカードなど、「どこからどこへ移ったか」を示すと操作が分かりやすくなる画面です。逆に、次の画面には入れないでください。

- 入力の手数が多い業務画面（受注入力、伝票登録など）。1回ごとの演出は短くても、1日に数百回繰り返す操作では待ち時間として積み上がる
- React Nativeと部品を共有している画面。DOM専用のため、ネイティブ側で同じ表示にならない
- ルーターが従来の`popstate`で戻る操作を処理している画面。リファレンスによると、Reactはこの場合のアニメーションを飛ばすため、戻る操作だけ動かない不揃いな画面になる

判断の軸は「動きが情報を運ぶか」です。装飾だけのアニメーションなら入れません。

### 19.2系に留まる場合に失う修正と不具合対応で更新を急ぐべき構成

19.2系の最新は7月21日の19.2.8で、10月11日時点でそれ以降のパッチは出ていません。19.3に破壊的変更は無いため、更新の手間は小さい部類です。特に、CSPでTrusted Typesを強制したいサイト、`useDeferredValue`や`<Activity>`の不具合に当たっているアプリは、19.3の修正を取り込むのが現実的な解決手段になります。

一方、新APIを急いで入れる必要はありません。まず版だけを上げて既存の画面が変わらないことを確かめ、ViewTransitionや`browser()`は画面の改修のついでに部分ごとに入れる、という2段階が安全です。React 19全体の変更点は[React 19とは？18からの変更点・新機能](https://www.issoh.co.jp/tech/details/4509/)で通して確認できます。版の更新と画面改修を同時に進める余力が社内に無い場合は、[業務用・Webアプリ開発](https://www.issoh.co.jp/service/apps/business/)で、既存Reactアプリの更新計画から改修までを請け負っています。

## React 19.3の新機能と既存アプリの更新についてのよくある質問

React 19.3の公開時期、互換性、新APIの使いどころについて、検索の多い質問に答えます。

### React 19.3はいつリリースされましたか？最新版はいくつですか？

2026年9月9日に19.3.0が公開されました。npm registryの記録では、10月11日時点で`react`と`react-dom`の`latest`タグは19.3.0のままで、パッチ版は出ていません。`npm view react version`で現在の最新版を確かめられます。

### React 19.3に破壊的変更はありますか？

公式ブログに破壊的変更や非推奨の記載はありません。ただしTransitionの並列描画など、既存の動きが変わる項目はあるため、版を上げたら遷移の多い画面とSSRのページを一通り動かしてください。

### ViewTransitionはReact Nativeでも使えますか？

使えません。React 19.3の`<ViewTransition>`はDOMでのみ動き、公式リファレンスはReact Nativeなど他の環境への対応を作業中としています。WebとReact Nativeで部品を共有している場合は、Web側だけで包むか、ネイティブ側は別のアニメーション手段で組む必要があります。

### ViewTransitionは未対応のブラウザでどう動きますか？

未対応ブラウザでの挙動はReactのリファレンスに明記が無いため、対象ブラウザの実機で確かめるのが確実です。19.3ではMobile Safariで`<ViewTransition>`が落ちる不具合が直っており、19.3より前のCanary版で試していた場合は版を上げてから確認してください。

### browser()とuseEffectのmountedフラグはどちらを使うべきですか？

19.3以降でSSRを使っているなら`use(browser())`を勧めます。mountedフラグは初回描画で一度空の表示を出し、その後に中身を差し替える仕組みなので、利用者に見える表示は2段階です。`browser()`はSuspenseのfallbackとして扱われるので、読み込み表示の出し方を他の非同期処理とそろえられます。ただしSuspense境界の内側で呼ぶことが条件です。

## 関連記事

- [React 19.2の新機能｜Activity・useEffectEvent・cacheSignal・PPRの使い方と19.2.8までの修正](https://www.issoh.co.jp/tech/details/9427/)：19.3の1つ前の版で入った機能と修正
- [Async Reactとは？Transition・Suspense・useOptimisticで非同期UIを組む実装【React 19.3】](https://www.issoh.co.jp/tech/details/11005/)：ViewTransitionの前提になるTransitionとSuspenseの書き方
- [View Transitions APIの対応ブラウザと実装手順｜クロスドキュメント遷移まで](https://www.issoh.co.jp/tech/details/2384/)：ReactのViewTransitionが使うブラウザAPIの仕組み
- [React Server Components（RSC）とは？サーバー・クライアントの違いと使い分けを実装例で解説](https://www.issoh.co.jp/tech/details/4003/)：Context直接描画とbrowser()の前提になる境界の考え方
- [ハイドレーションエラー（Hydration Error）とは？原因とReact / Next.jsでの対処法を解説](https://www.issoh.co.jp/tech/details/3218/)：browser()で避けられるSSRの食い違い

---

出典: [React 19.3の新機能｜ViewTransition・Fragment ref・browser()の実装と19.2からの更新手順](<https://www.issoh.co.jp/tech/details/18249/>)（株式会社一創）
