OpenAIReactApr 23, 2025, 12:00 AM

React Labs: View Transitions, Activity, and more

A condensed section focused on the key takeaways first.

Original Post

Quick Digest

Summary

A condensed section focused on the key takeaways first.

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

React Labs: View Transitions, Activity, and more

Key Points

  • ViewTransition and Activity available in experimental builds
  • addTransitionType lets you vary animations by transition cause
  • Activity shipped in react@19.2

Summary

React Labs released two experimental features you can try today and shared progress on several ongoing projects. The main releases are:

  • <ViewTransition>: a declarative component to mark what should animate during UI transitions. It leverages the browser startViewTransition API and activates on React transition triggers (startTransition, useDeferredValue, Suspense).
  • <Activity>: a component to hide/show parts of the UI (shipped in react@19.2).
  • addTransitionType: an API to declare the cause of a transition so you can apply different animations per cause.

These APIs are available in the experimental/canary releases (react@experimental / react-dom@experimental; some ViewTransition APIs are in react@canary). They have seen production testing but the final API may change.

Key Points

  • How to try

    • Upgrade to react@experimental and react-dom@experimental to test View Transitions and Activity.
    • Activity is already shipped in react@19.2; ViewTransition and addTransitionType are in react@canary.
  • ViewTransition basics

    • Wrap the element(s) you want to animate with <ViewTransition> to declaratively mark “what” should animate.
    • Transitions are triggered by React primitives: startTransition, useDeferredValue, and Suspense fallbacks.
    • Default behavior uses the browser’s cross-fade. Customize with ::view-transition-old / ::view-transition-new pseudo-selectors and class names.
    • Use the name prop to enable shared-element transitions between pages (React will match same-name ViewTransition elements).
    • Use default="none" or per-page control to opt out of global animations.
  • addTransitionType and conditional animations

    • Call addTransitionType("your-cause") inside a transition to label the cause (e.g., "nav-forward").
    • <ViewTransition> can accept a share prop mapping transition types to animation class names so you can vary animations by cause.
  • Activity

    • <Activity/> lets you hide/show UI regions; it is stable in react@19.2 but may be refined.
  • Other work in progress

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

Practical notes for engineers

  • Minimal opt-in: adding a single <ViewTransition> around route children can enable page cross-fades immediately when using startTransition-based navigation.
  • Style with the browser’s view-transition pseudo-selectors and CSS classes rather than imperative JS for most use cases.
  • Use addTransitionType to differentiate animations for forward/back navigation or other causes.
  • Expect API refinements: test on experimental/canary builds and provide feedback.

Full Translation

Translations

A translation section that keeps the flow of the original article.

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 サンプルは、公式のドキュメントとサンプルリポジトリを参照してください。)