OpenAIReact2025/04/23 0:00

React Labs: View Transitions, Activity, and more

要点だけを先に読めるように短く再構成したセクションです。

元記事

Quick Digest

要約

要点だけを先に読めるように短く再構成したセクションです。

openaijamodel: gpt-5-mini-2025-08-07

React Labs: View Transitions、Activity の公開と実験機能アップデート

Key Points

  • View Transitions が実験公開
  • <Activity /> は react@19.2 で出荷
  • addTransitionType で遷移原因を指定可能

Summary

React Labs が新たに実験的な UI 遷移機能を公開しました。主要な新機能は <ViewTransition>addTransitionType(react@canary / react@experimental)および <Activity />(react@19.2 に出荷)です。これらは実運用でテスト済みですが、最終 API はフィードバックにより変更される可能性があります。まずは react@experimental / react-dom@experimental にアップグレードして試してください。

Key Points

  • 導入手順

    • パッケージを最新の実験版に更新: react@experimentalreact-dom@experimental(一部は react@canary)。
    • まずはルートやルートごとに <ViewTransition> を追加して挙動を確認。
  • 基本的な使い方(何を・いつ・どう)

    • 何を: アニメーションさせたい領域を <ViewTransition> でラップ。
    • いつ: トリガーは startTransition(...)useDeferredValue(...)Suspense のフォールバック切替など。
    • どう: デフォルトはブラウザのクロスフェード。カスタムは ::view-transition-old / ::view-transition-new とクラスで定義。
  • 共有要素(shared element)

    • 同一要素を跨いで遷移させるには name を付与(例: name={video-${id}})。React が同名検出で共有遷移を有効化。
  • 遷移原因ごとのカスタマイズ

    • addTransitionType('nav-forward') のように原因を登録できる。
    • <ViewTransition share={{ 'nav-forward':'slide-forward', 'nav-back':'slide-back' }}> のように原因別にクラスを割り当てて CSS を切替。
  • 実践的な注意点

    • ルート全体を安易にラップすると不要な遷移が発生するので、ページ単位で default="none" や個別制御を検討。
    • 既存の CSS/JS アニメーションを置き換える目的ではなく、ナビゲーションや開閉などの UI 遷移向け。
    • プロダクションでの使用は可能だが、API 変更の可能性を考慮して段階的に導入すること。

Quick checklist for engineers

  • react / react-dom を実験版にアップデート
  • まずはページ遷移部分に <ViewTransition> を追加(ルート全体は避ける)
  • 必要に応じて nameshareaddTransitionType を使って共有遷移・原因別アニメーションを実装
  • ::view-transition-old / ::view-transition-new とクラスでアニメーションを定義

参考: ドキュメントに「How does <ViewTransition> work?」「Styling View Transitions」等の詳細ガイドあり。

Full Translation

翻訳

原文の流れを保ったまま読める翻訳セクションです。

openaijamodel: gpt-5-mini-2025-08-07

React Labs: View Transitions、Activity、その他

React Labs: View Transitions、Activity、その他

公開日: 2025-04-23

In React Labs の投稿では、研究・開発が進行中のプロジェクトについて紹介します。本投稿では、本日すぐに試せる 2 つの新しい実験的機能のドキュメント公開と、現在開発中の他の領域に関するアップデートを共有します。

今回リリースする実験的機能(テスト可能):

  • View Transitions
  • Activity

現在開発中の新機能(アップデート):

  • React Performance Tracks
  • Compiler
  • IDE Extension
  • Automatic Effect Dependencies
  • Fragment Refs
  • Concurrent Stores

新しい実験機能

注: <Activity />react@19.2 にて提供済みです。<ViewTransition />addTransitionType は現在 react@canary で利用可能です。View TransitionsActivityreact@experimental でもテストできます。これらの機能はプロダクションでのテストを経て安定していますが、フィードバックに応じて最終的な API が変わる可能性があります。

試すには React パッケージを最新の experimental バージョンにアップグレードしてください:

  • react@experimental
  • react-dom@experimental

以下で、アプリでの使い方を説明するか、新しく公開されたドキュメントを確認してください:

  • <ViewTransition> : Transition のアニメーションを有効にするコンポーネント
  • addTransitionType : Transition の原因(type)を指定する関数
  • <Activity> : UI の一部を隠したり表示したりできるコンポーネント

View Transitions

React の View Transitions は、アプリ内の UI トランジションにアニメーションを追加するのを簡単にする新しい実験的機能です。内部的には、ほとんどのモダンブラウザで利用できる startViewTransition API を使用します。

要素をアニメーション対象にするには、新しい <ViewTransition> コンポーネントでラップします:

// "what" to animate.
<ViewTransition>
  <div>animate me</div>
</ViewTransition>

このコンポーネントは、アニメーションが有効化されたときに「何を」アニメートするかを宣言的に定義できます。いつアニメートするかは、View Transition のトリガーとなる次の 3 つのうちいずれかを使って定義します:

// "when" to animate.
// Transitions
startTransition(() => setState(...));

// Deferred Values
const deferred = useDeferredValue(value);

// Suspense
<Suspense fallback={<Fallback/>}>
  <div>Loading...</div>
</Suspense>

デフォルトでは、これらのアニメーションはブラウザの View Transitions に適用されるデフォルトの CSS アニメーション(通常はスムーズなクロスフェード)を使用します。::view-transition 疑似セレクタを使って「どのように(how)」アニメーションするかを定義できます。例えば、すべてのトランジションのデフォルトアニメーションを変更するには:

// "how" to animate.
::view-transition-old(*) { animation: 300ms ease-out fade-out; }
::view-transition-new(*) { animation: 300ms ease-in fade-in; }

DOM が startTransitionuseDeferredValue、または Suspense の fallback からコンテンツへの切り替えのようなアニメーショントリガーで更新されると、React は宣言的なヒューリスティクスによりどの <ViewTransition> コンポーネントをアクティブ化するかを自動で決定します。ブラウザは CSS で定義されたアニメーションを実行します。

ブラウザの View Transition API に詳しい方は、ドキュメントの「How does <ViewTransition> Work」を参照してください。

以下では、View Transitions の利用例をいくつか見ていきます。まずはアプリ(現状、以下の操作に対してアニメーションが無い例):

  • ビデオをクリックして詳細表示
  • 「戻る」をクリックしてフィードに戻る
  • リストに入力してビデオをフィルタ

サンプルファイル: App.js、Details.js、Home.js、Icons.js、Layout.js、LikeButton.js、Videos.js、router.js

App.js (アニメーションなしのバージョン):

import TalkDetails from './Details';
import Home from './Home';
import { useRouter } from './router';

export default function App() {
  const { url } = useRouter();
  // 🚩This version doesn't include any animations yet
  return url === '/' ? <Home /> : <TalkDetails />;
}

注意: View Transitions は CSS や JS ベースのアニメーションを置き換えるものではありません

View Transitions はナビゲーション、展開、開閉、並び替えなどの UI トランジションに使うことを意図しています。アプリのすべてのアニメーションを置き換える目的ではありません。上の例では、既に「いいね」ボタンや Suspense のフォールバックのグリマーにアニメーションがあります。これらは特定の要素をアニメートしているため、従来の CSS アニメーションが適切です。

ナビゲーションのアニメート

このアプリには Suspense 対応のルーターがあり、ページ遷移は既に startTransition を使うようマークされています:

function navigate(url) {
  startTransition(() => { go(url); });
}

startTransition は View Transition のトリガーなので、ページ間のアニメーションに <ViewTransition> を追加できます:

// "what" to animate
<ViewTransition key={url}>{url === '/' ? <Home /> : <TalkDetails />}</ViewTransition>

URL が変わると <ViewTransition> と新しいルートがレンダリングされます。<ViewTransition>startTransition 内で更新されたため、その <ViewTransition> はアニメーション用にアクティブ化されます。デフォルトでは View Transitions はブラウザのデフォルトのクロスフェードアニメーションを含みます。

アプリにこれを追加するだけで、ページ間のナビゲーション時にクロスフェードが行われます:

import { ViewTransition } from 'react';
import Details from './Details';
import Home from './Home';
import { useRouter } from './router';

export default function App() {
  const { url } = useRouter();
  // Use ViewTransition to animate between pages.
  // No additional CSS needed by default.
  return (
    <ViewTransition>
      {url === '/' ? <Home /> : <Details />}
    </ViewTransition>
  );
}

ルーターがすでに startTransition を使用している場合、<ViewTransition> を追加するだけでデフォルトのクロスフェードで動作します。詳しくはドキュメント「How does <ViewTransition> work?」を参照してください。

<ViewTransition> アニメーションをオプトアウトする方法

ここでは簡単のためにアプリルート全体を <ViewTransition> でラップしましたが、これだとアプリ内のすべてのトランジションがアニメートされ、予期せぬアニメーションが発生する可能性があります。これを防ぐには、ルートの子を default="none" でラップして各ページが自身のアニメーションを制御できるようにします:

// Layout.js
<ViewTransition default="none">{children}</ViewTransition>

実際の運用では、ナビゲーションは enter/exit props や Transition Types を用いて行うべきです。

アニメーションのカスタマイズ

デフォルトでは <ViewTransition> はブラウザのデフォルトのクロスフェードを含んでいます。アクティベーションの仕方に応じて使用するアニメーションを <ViewTransition> の props で指定できます。例えばデフォルトのクロスフェードを遅くするには:

<ViewTransition default="slow-fade">
  <Home />
</ViewTransition>

次に CSS 側で .slow-fadeview-transition クラスで定義します:

::view-transition-old(.slow-fade) { animation-duration: 500ms; }
::view-transition-new(.slow-fade) { animation-duration: 500ms; }

これによりクロスフェードが遅くなります。

サンプル: App.js と animations.css に定義があります。詳細は「Styling View Transitions」を参照してください。

Shared Element Transitions(共有要素トランジション)

2 つのページに同じ要素が含まれる場合、その要素をページ間でアニメートしたいことがあります。これを行うには <ViewTransition> にユニークな名前を付与します:

<ViewTransition name={`video-${video.id}`}>
  <Thumbnail video={video} />
</ViewTransition>

これでビデオのサムネイルがページ間でアニメートします。

サンプル抜粋:

import { useState, ViewTransition } from "react";
import LikeButton from "./LikeButton";
import { useRouter } from "./router";
import { PauseIcon, PlayIcon } from "./Icons";
import { startTransition } from "react";

export function Thumbnail({ video, children }) {
  // Add a name to animate with a shared element transition.
  // This uses the default animation, no additional css needed.
  return (
    <ViewTransition name={`video-${video.id}`}>
      <div aria-hidden="true" tabIndex={-1} className={`thumbnail ${video.image}`}>
        {children}
      </div>
    </ViewTransition>
  );
}

export function VideoControls() {
  const [isPlaying, setIsPlaying] = useState(false);
  return (
    <span className="controls" onClick={() => startTransition(() => { setIsPlaying(p => !p); })}>
      {isPlaying ? <PauseIcon /> : <PlayIcon />}
    </span>
  );
}

export function Video({ video }) {
  const { navigate } = useRouter();
  return (
    <div className="video">
      <div className="link" onClick={(e) => { e.preventDefault(); navigate(`/video/${video.id}`); }}>
        <Thumbnail video={video}></Thumbnail>
        <div className="info">
          <div className="video-title">{video.title}</div>
          <div className="video-description">{video.description}</div>
        </div>
      </div>
      <LikeButton video={video} />
    </div>
  );
}

デフォルトでは、React は遷移でアクティベートされた各要素に対してユニークな名前を自動生成します(詳細は「How does <ViewTransition> work」を参照)。React が、名前付きの <ViewTransition> が削除され、同じ名前の新しい <ViewTransition> が追加される遷移を検出すると、共有要素トランジションがアクティベートされます。詳細はドキュメント「Animating a Shared Element」を参照してください。

トランジションの原因に応じたアニメーション

トリガーの仕方に応じて異なるアニメーションを適用したい場合があります。そのために addTransitionType という新しい API を追加しました。これによりトランジションの原因(type)を明示できます:

function navigate(url) {
  startTransition(() => {
    // Transition type for the cause "nav forward"
    addTransitionType('nav-forward');
    go(url);
  });
}

function navigateBack(url) {
  startTransition(() => {
    // Transition type for the cause "nav backward"
    addTransitionType('nav-back');
    go(url);
  });
}

トランジションタイプを使うと、<ViewTransition> に渡す props 経由でトリガーに基づいたカスタムアニメーションを提供できます。例えばヘッダーの "6 Videos" と "Back" に対して共有要素トランジションを追加する場合:

<ViewTransition
  name="nav"
  share={{ 'nav-forward': 'slide-forward', 'nav-back': 'slide-back' }}
>
  {heading}
</ViewTransition>

ここでは share prop を渡して、トランジションタイプに基づくアニメーションを定義しています。nav-forward からアクティブになった場合は slide-forward が適用され、nav-back の場合は slide-back が適用されます。

CSS でこれらのアニメーションを定義する例:

::view-transition-old(.slide-forward) { /* 前方にスライドする場合、"old" ページは左へスライドアウト */ }
::view-transition-new(.slide-forward) { /* 新しいページは右からスライドイン */ }
::view-transition-old(.slide-back) { /* 後方に戻る場合、"old" ページは右へスライドアウト */ }
::view-transition-new(.slide-back) { /* 新しいページは左からスライドイン */ }

(上記は説明用の概略です。具体的なアニメーション定義は Styling View Transitions を参照してください。)


この記事ではここまでで主に View Transitions の基本、カスタマイズ方法、共有要素トランジション、そして addTransitionType による原因ベースのアニメーション指定について説明しました。

次のセクションでは <Activity> を含む他の実験機能や、現在開発中の機能についてのアップデートを紹介します。

(注: 元記事の続きの具体的なコードや追加の CSS サンプルは、公式のドキュメントとサンプルリポジトリを参照してください。)