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
19
7.4k
React 19を概念から理解する
2024-05-29うひょさんに聞く! React 19アップデートの勘所
#React19_Findy
uhyo
May 28, 2024
Tweet
Share
More Decks by uhyo
See All by uhyo
require(ESM)とECMAScript仕様
uhyo
5
1.3k
TypeScript Quiz (Encraft #12 Frontend Quiz Night)
uhyo
7
1.4k
Shadow DOMとCSSの現状
uhyo
11
6.5k
TypeScriptってどんな言語? 言語そのものを知る面白さ
uhyo
16
8.5k
App Router時代のデータ取得アーキテクチャ
uhyo
47
15k
ステート管理を超えるRecoil運用の考え方
uhyo
15
12k
ついに来る!TypeScript5.0の新機能
uhyo
21
16k
TypeScript 4.7と型レベルプログラミング
uhyo
6
5.4k
TypeScriptを振り回せ!
uhyo
28
9k
Other Decks in Technology
See All in Technology
NAB Show 2024 動画技術関連レポート/ NAB Show 2024 Report
cyberagentdevelopers
PRO
3
250
Spring Boot 2.7 から 3.1 への アップグレードに苦労したことと学んだこと
kometsubu
2
240
自分の学習データで画像生成AIを使ってみる話
moyashi
2
170
オブジェクト指向考古学 〜人類は再びDCIの夢を見るか〜
a_suenami
4
890
リードタイム、コストを最適化しながら 回復性を求めるクラウドネイティブ戦略 #CNDS2024
sgrokym
1
220
AWS構成図から CloudFormationとパラメータシートを 自動生成するシステムを作ってみた
tsukuboshi
0
120
AWSネイティブなセキュリティを考える
wkm2
1
140
成長し続けるTVerサービスを支える オブザーバビリティとカスタマーサポート
techtver
PRO
2
710
不要な DNS リソースレコードは消そう / Delete unused DNS records
wa6sn
4
3.1k
Power Automateのデータ操作(Data Operation)について (Ver.モダンデザイナー)
miyakemito
4
430
10分でわかる株式会社ログラス − エンジニア向け会社説明資料 / Loglass in 10 min for Engineers
loglass2019
3
15k
オブザーバビリティ勉強会で模擬障害対応をやってみた
leveragestech
1
360
Featured
See All Featured
Web Components: a chance to create the future
zenorocha
306
41k
[RailsConf 2023] Rails as a piece of cake
palkan
31
4.2k
Rails Girls Zürich Keynote
gr2m
91
13k
Testing 201, or: Great Expectations
jmmastey
32
6.8k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
24
1.7k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
23
2k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
27
1.7k
RailsConf 2023
tenderlove
11
630
Six Lessons from altMBA
skipperchong
22
3.1k
Designing on Purpose - Digital PM Summit 2013
jponch
112
6.6k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
42
4.6k
How GitHub (no longer) Works
holman
305
140k
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を使いこなす近道となる。