1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

React 19 新機能 フォーム・非同期・状態管理 のアップデート

1
Posted at

参考: React 19 公式ブログ


React 19 以前のアップデート振り返り

React 16.8(2019)— Hooks の登場

  • useState
  • useEffect
  • useContext
  • useReducer

→ React 開発の基礎ができた

React 18(2022)— 「非同期 UI」がテーマ

  • Concurrent Rendering
  • useTransition
  • useDeferredValue
  • Suspense 強化
  • Streaming SSR

React 19 の概要

フォームを送信して API を叩き、結果で state を更新する処理は React アプリの定番パターン。

これまでは「送信中のローディング表示」「エラーハンドリング」「レスポンスに応じた state 更新」「リクエストの順序管理」などを全部自分で書く必要がありましたが、React 19 では 非同期処理をトランジションの中に書くだけで、これらを自動でやってくれるようになります。


追加機能一覧


Actions

これまで

onSubmit
↓
fetch
↓
loading 管理
↓
error 管理
↓
state 更新

React 19 では

<form action={action}>

action に関数を渡すだけで処理できます。


useActionState

Action の状態を管理するための Hook

const [state, formAction, isPending] = useActionState(actionFn, 初期値);
戻り値 説明
state Action 関数の戻り値(現在の状態)
formAction form の action に渡す関数
isPending Action 実行中かどうか(boolean)

第一引数のアクション関数の戻り値が、そのまま state に反映されます。

コード例

"use client";

import { useActionState } from "react";

type State = {
  message: string;
};

async function submitForm(prevState: State, formData: FormData): Promise<State> {
  await new Promise((resolve) => setTimeout(resolve, 2000));
  const name = formData.get("name");
  return { message: `${name} さんの送信が完了しました` };
}

export default function Page() {
  const [state, formAction, isPending] = useActionState(submitForm, { message: "" });

  return (
    <form action={formAction}>
      <input name="name" placeholder="名前" />
      <button disabled={isPending}>
        {isPending ? "送信中..." : "送信"}
      </button>
      <p>{state.message}</p>
    </form>
  );
}

useActionState = Action の状態を管理する Hook


useFormStatus

<form> の送信状態を、子コンポーネントが直接読み取れる Hook

React 18 では子コンポーネントに pending を props で渡すバケツリレーが必要でした。useFormStatus は Context のような仕組みで、これを不要にします。

const { pending, data, method, action } = useFormStatus();
プロパティ 説明
pending 送信中かどうか(boolean)
data 送信中のみ取得できる FormData
method form の method("get" / "post" など)
action 現在実行中の action 関数

⚠️ 重要な制約: 必ず <form> タグの「子コンポーネント」内で使うこと

コード例

"use client";

import { useFormStatus } from "react-dom";

function SubmitButton() {
  const { pending, data, method, action } = useFormStatus();

  return (
    <div>
      <button disabled={pending}>
        {pending ? "送信中..." : "送信"}
      </button>
      <p>入力値: {data?.get("name")?.toString()}</p>
      <p>method: {method}</p>
      <p>action: {action?.name}</p>
    </div>
  );
}

async function submitForm(formData: FormData) {
  await new Promise((resolve) => setTimeout(resolve, 3000));
  console.log(formData.get("name"));
}

export default function Page() {
  return (
    <form action={submitForm} method="post">
      <input name="name" placeholder="名前" />
      <SubmitButton />
    </form>
  );
}

useFormStatus = 親 form の送信状態を子コンポーネントで props なしに読める Hook


useOptimistic

サーバーの返事を待たずに、先に画面だけ更新する Hook(Optimistic = 楽観的)

const [optimisticState, addOptimisticUpdate] = useOptimistic(state, updateFn);
戻り値 説明
optimisticState 今画面に見せている状態(本物 + 仮の更新)
addOptimisticUpdate 先に見せたい更新をかける関数

通常のフロー

ボタン押下 → API 通信 → 成功 → 画面更新

useOptimistic を使ったフロー

ボタン押下 → 先に画面更新 → API 通信 → 成功

いいね・コメント投稿・チャット送信などに向いています。

コード例

"use client";

import { useOptimistic, useState } from "react";

export default function Page() {
  const [likes, setLikes] = useState(0);

  const [optimisticLikes, addOptimisticLike] = useOptimistic(
    likes,
    (currentLikes) => currentLikes + 1
  );

  async function likeAction() {
    addOptimisticLike();
    await new Promise((resolve) => setTimeout(resolve, 2000));
    setLikes((prev) => prev + 1);
  }

  return (
    <div>
      <p>いいね数: {optimisticLikes}</p>
      <button onClick={likeAction}>いいね</button>
    </div>
  );
}

useOptimistic = サーバー処理の完了を待たずに、先に UI を更新するための Hook


use()

Promise や Context の値を読み取るための API

const data = use(promise);

これまで

useEffect → fetch → useState に保存 → 画面表示

React 19 では

Suspense と組み合わせることで Promise の結果を直接扱えます。

コード例

import { use, Suspense } from "react";

const fetchUser = async () => {
  await new Promise((resolve) => setTimeout(resolve, 2000));
  return { name: "Luke" };
};

const userPromise = fetchUser();

function User() {
  const user = use(userPromise);
  return <p>{user.name}</p>;
}

export default function Page() {
  return (
    <Suspense fallback={<p>読み込み中...</p>}>
      <User />
    </Suspense>
  );
}

Promise が完了するまでは Suspense の fallback が表示されます。

use() = Promise の結果をコンポーネント内で直接読み取る API


ref as Props

ref を通常の props のように渡せる機能

React 19 以前

子コンポーネントに ref を渡す場合、forwardRef が必要でした。

const Input = forwardRef((props, ref) => {
  return <input ref={ref} />;
});

React 19 では

function Input({ ref }) {
  return <input ref={ref} placeholder="名前" />;
}

forwardRef なしで ref を渡せます。

コード例

"use client";

import { useRef } from "react";

function Input({ ref }) {
  return <input ref={ref} placeholder="名前" />;
}

export default function Page() {
  const inputRef = useRef(null);

  function focusInput() {
    inputRef.current?.focus();
  }

  return (
    <div>
      <Input ref={inputRef} />
      <button onClick={focusInput}>input にフォーカス</button>
    </div>
  );
}

ref as Props = ref を通常の props のように扱える機能


Context Provider 簡略化

React 19 以前

<ThemeContext.Provider value={theme}>
  <App />
</ThemeContext.Provider>

React 19 では

<ThemeContext value={theme}>
  <App />
</ThemeContext>

.Provider を書かなくても Context を渡せるようになりました。

コード例

import { createContext, useContext } from "react";

const ThemeContext = createContext("light");

function Child() {
  const theme = useContext(ThemeContext);
  return <p>現在のテーマ: {theme}</p>;
}

export default function Page() {
  return (
    <ThemeContext value="dark">
      <Child />
    </ThemeContext>
  );
}

Context Provider 簡略化 = <Context.Provider> の代わりに <Context> と書ける機能


まとめ

機能 概要
Actions フォーム送信や非同期処理を扱いやすくする仕組み
useActionState Action の実行結果を state として管理する Hook
useFormStatus 親 form の送信状態を子コンポーネントで参照する Hook
useOptimistic サーバー処理を待たずに先に UI を更新する Hook
use() Promise の結果をコンポーネント内で直接読み取る API
ref as Props ref を通常の props のように渡せる機能
Context Provider 簡略化 <Context.Provider><Context> と書けるようになった

React 19 は、フォーム・非同期処理・状態管理・Context・ref 周りをよりシンプルに書けるようにしたアップデートです。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?