Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
React 19を概念から理解する
Search
uhyo
May 28, 2024
Technology
22
10k
React 19を概念から理解する
2024-05-29うひょさんに聞く! React 19アップデートの勘所
#React19_Findy
uhyo
May 28, 2024
Tweet
Share
More Decks by uhyo
See All by uhyo
React 19アップデートのために必要なこと
uhyo
5
880
color-scheme: light dark; を完全に理解する
uhyo
7
470
React 19 + Jotaiを試して気づいた注意点
uhyo
9
2.9k
TypeScriptの次なる大進化なるか!? 条件型を返り値とする関数の型推論
uhyo
3
2.9k
tsconfig.jsonの最近の新機能 ファイルパス編
uhyo
8
3.3k
非同期処理を活用しながらRust製wasmとJSを連携する方法(wasm-bindgenを使いたくない人向け)
uhyo
4
4.1k
tsconfig.jsonの設定を見直そう!フロントエンド向け 2024夏
uhyo
26
10k
require(ESM)とECMAScript仕様
uhyo
7
2.2k
TypeScript Quiz (Encraft #12 Frontend Quiz Night)
uhyo
8
1.8k
Other Decks in Technology
See All in Technology
Autonomous Database Serverless 技術詳細 / adb-s_technical_detail_jp
oracle4engineer
PRO
17
45k
ソフトウェアエンジニアと仕事するときに知っておいたほうが良いこと / Key points for working with software engineers
pinkumohikan
1
130
深層学習と古典的画像アルゴリズムを組み合わせた類似画像検索内製化
shutotakahashi
1
290
日経のデータベース事業とElasticsearch
hinatades
PRO
0
170
短縮URLをお手軽に導入しよう
nakasho
0
130
Windows の新しい管理者保護モード
murachiakira
0
190
依存パッケージの更新はコツコツが勝つコツ! / phpcon_nagoya2025
blue_goheimochi
3
190
ホワイトボードチャレンジ 説明&実行資料
ichimichi
0
140
白金鉱業Meetup Vol.17_あるデータサイエンティストのデータマネジメントとの向き合い方
brainpadpr
7
950
Helm , Kustomize に代わる !? 次世代 k8s パッケージマネージャー Glasskube 入門 / glasskube-entry
parupappa2929
0
280
データ資産をシームレスに伝達するためのイベント駆動型アーキテクチャ
kakehashi
PRO
2
650
Iceberg Meetup Japan #1 : Iceberg and Databricks
databricksjapan
0
240
Featured
See All Featured
A better future with KSS
kneath
238
17k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
How STYLIGHT went responsive
nonsquared
98
5.4k
Optimizing for Happiness
mojombo
376
70k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
4
360
Adopting Sorbet at Scale
ufuk
74
9.2k
Git: the NoSQL Database
bkeepers
PRO
427
65k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
2.1k
Java REST API Framework Comparison - PWX 2021
mraible
29
8.4k
Scaling GitHub
holman
459
140k
Unsuck your backbone
ammeep
669
57k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
366
25k
Transcript
React 19を 概念から理解する 2024-05-29うひょさんに聞く! React 19アップデートの勘所 #React19_Findy
発表者紹介 uhyo 株式会社カオナビ フロントエンドエキスパート ずっとTypeScriptとReactで仕事している。 好きなReactの機能はやっぱりSuspense。
React 19 RC 4月25日にBeta、 5月15日にRCが 公開。あわせて ブログも公開された。 https://react.dev/blog/2024/04/25/react-19
This Talk React 19 RCのブログ記事や、すでに公開 されているReactのドキュメントをベースに React 19の機能を解説。 具体的なAPIを細かく見ていくというよりは、 React
19時代に重要になる大まかな概念を 理解することを目指す。
Reactのこれまで React 0.14 … 神話の時代 React 15 … クラスコンポーネント全盛期 React
16 … フックの時代(正確には16.8から) React 17 … No New Features React 18 … Suspenseの時代
React 19は何の時代になる?
React 19は何の時代になる?
React 19は何の時代になる? React 0.14 … 神話の時代 React 15 … クラスコンポーネント全盛期
React 16 … フックの時代(正確には16.8から) React 17 … No New Features React 18 … Suspenseの時代 React 19 … Actionsの時代
Actionsとは?
Actionsとは?
Actionsとは? By convention, functions that use async transitions are called
“Actions”. 非同期トランジションを使う関数のことを、 慣例的に “Actions” と呼ぶことにします。
Actionsとは? By convention, functions that use async transitions are called
“Actions”. 非同期トランジションを使う関数のことを、 慣例的に “Actions” と呼ぶことにします。 ?
余談: Reactのドキュメントについて より分かりやすくActionsを説明したいところだが、 発表者の経験的に、Reactの新概念は めちゃくちゃ調べたり実験したりして自分なりの 素晴らしい説明が書けたと思ったら、 公式ドキュメントに同じことが最初から書いてあった ということがよくある。
余談: Reactのドキュメントについて なので、公式の情報に正面から向き合い、 書いてあることを全部妥協せずに理解するのが Reactの新概念を深く正確に理解する最短ルート である。 (現時点ではまだドキュメントの更新が追いついていない ところもありそうなので、実験と気合で補いましょう)
Actionsとは? By convention, functions that use async transitions are called
“Actions”. 非同期トランジションを使う関数のことを、 慣例的に “Actions” と呼ぶことにします。
非同期トランジションとは トランジションという概念は、React 18ですでに 導入されていた。(useTransition) 非同期の部分はReact 19の新しい概念である。 ページ遷移とかで使われるView Transition APIは関係ないので 気を付けよう!
CSSのtransitionも関係ないです
トランジションの復習 (React 18でのトランジション) const [isPending, startTransition] = useTransition(); // イベントハンドラとかで
startTransition(() => { setIsOpen(true); // 何らかのステート更新 });
トランジションの復習 startTransition(() => { setIsOpen(true); // 何らかのステート更新 }); startTransitionのコールバック内で行われた ステート更新はトランジションとなり、
優先度が低いステート更新として扱われる。
トランジションの性質 普通のステート更新: 更新後のレンダリング結果をすぐに・絶対に描画する。 レンダリングに時間がかかる場合、完了するまで 次のステート更新はできない。 優先度が低いステート更新(トランジション): レンダリングに時間がかかる場合は描画を遅延できる。 別のステート更新で割り込んだり、ステートを 再度更新してレンダリングをキャンセルしたりできる。
isPendingの挙動 const [isPending, startTransition] = useTransition(); トランジションの場合、ステート更新の結果が即座にUIに 反映されないこともある。その間、isPendingがtrue で レンダリングされる。
(トランジションのステート更新の反映はまだされずに、 isPendingだけがtrueになる)
Suspenseとトランジションの関係 トランジションのステート更新によって サスペンドが発生した場合も、レンダリングに 時間がかかる場合に準じた扱いとなる。 ステート更新後のUI(=Suspenseのfallback)が 出る代わりに、更新前のUIを維持したままで isPendingがtrueになる。 (優先度の低いステート更新なので更新前のUIを維持することが許容される)
Suspenseとトランジションの雑な例 const [userId, setUserId] = useState(0); const userProfile = use(dataSource.getUser(userId));
// … startTransition(() => { setUserId(123); // ステート更新したらサスペンド発生 });
React 18までのトランジションまとめ 優先度の低いステート更新をするためのAPI。 時間のかかるレンダリングの最中に 他のステート更新を受け付けたり、 サスペンドを起こしたレンダリングの最中に サスペンド前のUIを残し続けたり することができる。
宣伝 React 18までのトランジションについて、 細かな挙動まで含めて解説したZenn本
React 19の非同期トランジション startTransition(async () => { const result = await
updateStuff(); setMessage( result.success ? “success!” : “ouch!” ); }); 非同期関数を渡せる (この非同期関数がアクション)
React 19の非同期トランジション startTransition(async () => { const result = await
updateStuff(); setMessage( result.success ? “success!” : “ouch!” ); }); 非同期トランジションの実行中は isPendingがtrueになる。 完了したらfalseに戻る。 もちろん、トランジション内 でステート更新できる。
React 19の非同期トランジション 非同期処理の間isPendingがtrueになる点で、 非同期トランジションの挙動は、 普通のトランジション + Suspenseと同じ。 Q. どちらを使えばいいか?
React 19の非同期トランジション 非同期処理の間isPendingがtrueになる点で、 非同期トランジションの挙動は、 普通のトランジション + Suspenseと同じ。 Q. どちらを使えばいいか? A.
参照系はSuspense、更新系は非同期トランジション Suspenseは参照系向けのAPIで、更新系には向いて いなかった。非同期トランジションでそこが補完された。
React 19の非同期トランジション 公式ドキュメントにも Actions automatically manage submitting data for you
という記載があり、 非同期トランジション(アクション)が更新系の サポートを意図したAPIであることが分かる。
アクションに関係する新しいAPI •useOptimistic • UIの楽観的更新を書きやすくするためのフック •useActionState • アクションの状態管理を楽に行うためのフック
useOptimistic
useOptimisticによる楽観的更新 楽観的更新とは、更新リクエストを送ったあと、 レスポンスが返ってくる前に更新後の状態を UIに反映させること。 例: Xで「いいね」を押すと、押した瞬間にUI上では いいね数が1増える(レスポンスが返ってくるのを待たない)
楽観的更新の面倒さ ステート管理が煩雑になりがち。 • エラー時に戻すことを考えると、元データを上書きできない • エラー時にステートを戻す処理を行いたいので ErrorBoundaryを活かせない
useOptimisticの使い方(宣言側) const [likes, setLikes] = useState(0); const [dispLikes, addOptimistic] =
useOptimistic( likes, (currentLikes, optimisticValue) => { return currentLikes + optimisticValue; } );
useOptimisticの使い方(宣言側) const [likes, setLikes] = useState(0); const [dispLikes, addOptimistic] =
useOptimistic( likes, (currentLikes, optimisticValue) => { return currentLikes + optimisticValue; } ); 元データの“楽観的更新版”のステートを宣言できる。 楽観的更新版 元データ
useOptimisticの使い方(更新側) const [dispLikes, addOptimistic] = useOptimistic(…); startTransition(async () => {
addOptimistic(1); // 楽観的更新で1を足す const newLikes = await api.postLike(); setLikes(newLikes); // 元データを更新 });
useOptimisticの使い方(更新側) const [dispLikes, addOptimistic] = useOptimistic(…); startTransition(async () => {
addOptimistic(1); // 楽観的更新で1を足す const newLikes = await api.postLike(); setLikes(newLikes); // 元データを更新 }); 非同期トランジションの中でaddOptimisticを呼び出す ことで、楽観的更新として反映される。
useOptimisticの動作例 const [likes, setLikes] = useState(0); const [dispLikes, addOptimistic] =
useOptimistic( likes, (currentLikes, optimisticValue) => { return currentLikes + optimisticValue; } ); startTransition(async () => { addOptimistic(1); const newLikes = await api.postLike(); setLikes(newLikes); }); likes = 10 optimisticValue = 1 ① 非同期トランジション開始 → addOptimistic呼び出し dispLikes = 10 + 1 = 11 ⇒
useOptimisticの動作例 const [likes, setLikes] = useState(0); const [dispLikes, addOptimistic] =
useOptimistic( likes, (currentLikes, optimisticValue) => { return currentLikes + optimisticValue; } ); startTransition(async () => { addOptimistic(1); const newLikes = await api.postLike(); setLikes(newLikes); }); likes = 11 ② ステート更新して トランジション終了 (楽観的更新状態ではなくなる) dispLikes = 11 ⇒
useOptimisticまとめ アクションの中で addOptimisticを呼び出すことで 楽観的更新を行う。 「アクションの実行中は楽観的更新の内容が表示される」 「アクションが完了したら自動的に元に戻る」 というシンプルな挙動であり、 アクションの概念を理解した人にとっては分かりやすい。
useOptimistic補足 Q. なぜ楽観的更新後の値を直接指定するのではなく関数を 介するのか? const [likes, setLikes] = useState(0); const
[dispLikes, addOptimistic] = useOptimistic( likes, (currentLikes, optimisticValue) => { return currentLikes + optimisticValue; } );
useOptimistic補足 Q. なぜ楽観的更新後の値を直接指定するのではなく関数を 介するのか? A. 元の値が変化した場合や複数トランジションが走って いる場合にも対応するため
useActionState
useActionStateの概要 新しいステートを宣言するフック。 ステートの初期値と、 ステートを更新するためのアクションを受け取る。 ある意味useReducerに近い点もあるフック。
useActionStateの使い方(宣言側) const [state, runAction, isPending] = useActionState(async () => {
const result = await api.postLike(); return result; }, null, ); ステートを保持 ステートの初期値 アクションの返り値でステート更新
useActionStateの使い方(呼び出し側) const [state, runAction, isPending] = useActionState(async () => {
… }, null); … <button type=“button” onClick={runAction} /> useActionStateから返ってきた関数を 呼び出せばアクションが実行される
useActionStateとトランジション const [state, runAction, isPending] = useActionState(async () => {
… }, null); useActionStateから得られたrunActionを実行すると、 自動的に非同期トランジションになる。 (useActionStateにuseTransition相当の機能も 内包されている)
useActionStateまとめ useTransitionとuseStateをくっつけた 便利なフック。 あるいはuseReducerの非同期版。 これがあるので、非同期トランジションのために useTransitionを直接使うことは少ないかも。
useActionStateの追加機能 実は、連打したときにアクションが 複数並列実行されないように制御してくれる。 useReducerの非同期版と考えれば、並列実行 できないのは自然か。(Quramyさんの受け売り [1]) [1] Server Actions の同時実行制御と画面の状態更新
https://quramy.medium.com/server-actions- %E3%81%AE%E5%90%8C%E6%99%82%E5%AE%9F%E8%A1%8C%E5%88%B6%E5%BE%A1%E3%81%A8%E7% 94%BB%E9%9D%A2%E3%81%AE%E7%8A%B6%E6%85%8B%E6%9B%B4%E6%96%B0-35acf5d825ca
<form>とアクション
<form>の新機能 react-domの新機能として、<form>の action属性にアクションを渡せるようになった。 フォームが送信されると呼び出される。
<form>のactionにアクションを渡す <form action={async () => { addOptimistic(1); const newLikes =
await api.postLike(); setLikes(newLikes); }}> … </form> アクションなので useOptimisticにも対応
<form>のisPendingを取得したい アクションということはisPendingの概念があるはず。 それはuseFormStatusで取得できる。 const { isPending } = useFormStatus(); (非制御コンポーネントやサーバー関係の諸々のために
FormDataを取得できる機能もある) <form>の中のコンポーネント で呼び出す必要がある
useActionStateとの組み合わせ <form>の外から状態を管理したい場合に有効。 const [state, runAction, isPending] = useActionState(async () =>
{ … }, null); <form action={runAction}>…</form>
Server Actionsとの関係は?
Server ActionsとActionsの関係 Q. ここまで見てきたアクションと、Next.jsとかで出て くるServer Actionsの関係は?
Server ActionsとActionsの関係 Q. ここまで見てきたアクションと、Next.jsとかで出て くるServer Actionsの関係は? A. Server Actionsはクライアントから見たら非同期関数。 非同期関数はだいたいアクションである。
使う側から見れば、Server Actionsはアクションの一種。
Server Actionsに関係するAPI <form>のactionやuseActionStateは、 Server Actionsと特に深い関係にある。 今回はサーバー周りまで踏み込む時間がないので 省略。
アクション系以外の 新機能ダイジェスト
メタデータ <title>, <link>, <meta> をレンダリング するとheadに反映してくれる。便利。 <article> <h1>{post.title}</h1> <title>{post.title}</title> <link
rel=“canonical” href=“https://...” />
スタイルシート <link rel=“stylesheet”>や<style>も レンダリング可能。しかもSuspense対応。 (スタイルシートが読み込まれるまでサスペンドして コンポーネントの表示を待ってくれる) <div className=“card”> <link rel=“stylesheet”
href=“…” precedence=“default” /> …
スクリプト <script>もasync属性を付けることで サスペンド対応になる。謎のサードパーティ スクリプトを読み込む必要があるときに便利。 <div> <script async src=“nazo_gadget.js” /> <button
onClick={() => NazoGadget.start()} /> </div>
Contextを直接コンポーネントとして 使えるやつ const MyContext = createContext(); // これまで <MyContext.Provider value={…}>
// これから <MyContext value={…}>
ほか多数 他にも細かな改善がいろいろ入っていますが、 全部紹介する時間もないのでまた今度。
ほか多数 他にも細かな改善がいろいろ入っていますが、 全部紹介する時間もないのでまた今度。
None
Zenn本「React 19新機能まるわかり」 このイベント終了後に配信開始 ¥0 (税込) アクション周りの話はもちろん、 今回紹介しきれなかった React 19の新機能を全部 詰め込んだZenn本が新登場。
React 19へのアップグレード
React 19の破壊的変更 メジャーバージョンアップなので破壊的変更がある。 内容的に、破壊力は控えめの印象。
古い機能の削除 すでに非推奨化済の古い機能がいろいろ削除される。 5年以上メンテされていないコードや外部ライブラリ がある人は要注意。 • 関数コンポーネントのdefaultProps • Legacy Context •
String refs • など
TypeScript型定義の破壊的変更 こちらのほうが破壊力高いが、ランタイムの変更 ではないのでまだマシ。 const myRef = useRef<HTMLDivElement>(); React.MutableRef<HTMLDivElement> const [state,
dispatch] = useReducer<FuncType>(); 引数の無いuseRefは不可になった MutableRefという型はAPIで 使われなくなり、非推奨になった useReducerの型引数は 破壊的変更が入った
まとめ
まとめ React 19で新しく登場したAPIたちは、 アクションという新概念でまとめられている。 (今回省略したuseはまた別) Suspenseやトランジションという既存概念を 土台にアクションを理解することが React 19を使いこなす近道となる。