
24,026 文字

ReactチームからFetchが登場してから、特に新機能や開発中のものについての発表を聞く機会はあまりありませんでしたが、それが今日、React Labsからのアップデートで変わりました。ここでは彼らが開発している実験的な機能が紹介されています。すべてのものがReactに取り込まれるわけではありませんが、重要なのはそれが取り込まれるかどうかではなく、彼らが何に取り組んでいるか、そしてそれがどれだけ関連性があるかです。
もしサーバーコンポーネントの話にうんざりしているなら理解できます。ここで紹介するものはサーバーコンポーネントとは関係ありません。これはすべてのReact開発者にとって本当に役立つものです。アニメーションとトランジションに関するすべての機能のオーバーホールから、IDE拡張機能まで(そう、ReactチームがVS Code向けの拡張機能をリリースします)、非常に多くのクールな機能があります。
彼らは速いペースで開発しており、ここでは多くの内容をカバーしますが、私たちも前進しており、チームに給料を払う必要があるので、今日のスポンサーについて簡単にお話ししてから、すぐに本題に入りましょう。
今日のスポンサーは少し異なります。以前にもスポンサーとして登場したことのある会社ですが、皆さんがまだ見たことがない可能性のある製品でもあります。なぜなら私が彼らに作らせたからです。本当です。私はConvexに独自のAIアプリビルダーを作るよう説得しました。そして彼らがそれを実現してくれて本当に嬉しいです。なぜならそれはAIアプリビルダーができないと思っていたことができるからです。
詳細については専用のビデオがありますが、ハイライトをお伝えすると、彼らが構築したSlackクローンがあります。このSlackクローンには、従来のSlackと同じように作成できる完全に機能するチャンネルがあります。テストチャンネルで(間違えてしまいましたが)、ここでメッセージを送信できます。2つ目のプレビュー環境を作成し、匿名でサインインすると、メッセージを送信するたびに他のプレビューに自動的に表示されます。
さらにクールなのはデータベースタブです。ここでメッセージに移動し、「hey」というメッセージを「what’s good」に変更すると、データベースでの変更がUIに反映されます。これはConvexのすべての利点を享受しているからです。どこかで変更が発生すると、自動的に他の場所にも同期される機能や、実際のサーバーサイドコードを実行する機能、わずか3行のコードでOAuthをセットアップする機能、ファイルアップロードなど、通常なら時間がかかる面倒なことを簡単に実現できます。
これを構築するのにどれくらい時間がかかったと思いますか?信じられないかもしれませんが、これは1回のプロンプトで作成されました。文字通り1つのプロンプトで、問題なくこれをすべて生成しました。構築には1分ほどかかり、完全に機能するバックエンドと、このプロダクション対応アプリをワンクリックでデプロイするボタンがあります。
Chefは、実際にバックエンドを理解し、快適に出荷できる方法で構築する唯一のAIアプリビルダーだと言っても過言ではありません。他のツールはすべて統合がめちゃくちゃで、通常は良いフロントエンドを生成するために使用し、その後自分でバックエンドを構築しに行きます。バックエンドを自分でやる必要がないプラットフォームを持つことは本当にクールです。それは正しく行われ、その理由はConvexがコードを書いて正常に動作させるための最高のバックエンドアズアサービスソリューションの1つを持っているからです。
実際のアプリをAIアプリビルダーで構築したい場合、Chefが唯一推奨できるものです。soyb.link/chefで今すぐチェックしてください。
拡張機能の部分にスキップしたい衝動と戦っています。その部分にスキップするのは理解できますが、ここで話さなければならない重要なことが多くあります。今日現在、Reactの実験的ブランチにはビュートランジションとアクティビティが追加されました。これを長い間待っていました。
ビュートランジションに馴染みがないかもしれないのは、Firefoxベースのブラウザを使用しているからかもしれません。そうするとブラウザでは機能しません。私のお気に入りのサイトの一つはNeanのブログです。Neanはかつてメタで働いていたエンジニアで、現在はOpenAIにいます。彼はStylexを含むクレイジーなスタイル関連のものを構築し、Metaのスタイリングのほとんどを強化しています。彼のブログはビュートランジションの素晴らしいショーケースです。Firefoxベース以外のブラウザを使用している場合に見ることができます。
Chromeベースのブラウザに切り替えて、異なるページに移動するとき、ネオンが上に移動するアニメーションが見えますか?それはクレイジーなJavaScriptとCSSではなく、ビュートランジションというブラウザAPIで、ブラウザに「このエレメントは次のページにも存在するかもしれない、もしそうなら、そこに移動する際にアニメーションを付けて」と伝えることができます。
このブログ記事のタイトルをクリックしたとき、それがどれだけクールか見えましたか?これは本当に素晴らしいです。ビュートランジションはナビゲーション時に発生し、要素が移動または変化する場合に、その要素の移動方法や変化方法を定義することができます。だからこれがとてもクールに見えるのです。特に難しいことではありません。
私のブログに行くと、これがどのように見えるかお見せできます。ランダムな投稿をクリックすると、これにもまだ素敵な小さなアニメーションがあります。実際に動かすものは何もないので周りに何かを動かすわけではありませんが、そのアニメーションは追加するのがとても簡単でした。
このサイトにはJSが全くないことも注目に値します。完全にAstroで作られています。おそらく一部のことをトリガーするための小さなルーターがあるかもしれませんが、このコードは驚くほど単純です。
Astroのトランジションからビュートランジションを見つけると、それはただヘッドにあるだけです。なぜならそれは単にいくつかのJSをマウントしているだけだからです。そして、あるページから別のページへ何かを移動させたい場合は、それを識別するためにタグを付けるだけです。このCSSスニペットを追加するだけで、アプリの異なるルート間のナビゲーションがはるかに良く感じるようになります。とてもクールです。それでクレイジーなことができますが、ナビゲーションだけではありません。
DOMを更新するビュートランジションをトリガーすることもでき、そのアニメーションが発生します。これはシングルページアプリに最適です。カードを削除するとアニメーションで消えていく例があります。これはブラウザで最も難しいことの一つです。DOMから何かを削除すると、それはもう存在しないので、アニメーション化できません。しかし、ビュートランジションを使えば、突然それをアニメーション化できるようになります。DOMからの要素の削除が、発生するイベントになるからです。Firefoxをターゲットにしていない限り、近い将来に追いつくことを願っています。
Reactはビュートランジションをサポートするようになりました。これにとても興奮しています。もうクレイジーで混沌としたライブラリを使って削除ボタンをクリックしたときに何かがフェードアウトするようにする必要はありません。
アニメーション化する要素にオプトインするには、新しいビュートランジションコンポーネントでラップします。このコンポーネントを使用すると、アニメーションがアクティブ化されたときにアニメーション化する対象を宣言的に定義できます。ビュートランジションをトリガーするタイミングは、3つのトリガーのいずれかを使用して定義できます。startTransitionを呼び出すか、deferredを呼び出すか、Suspenseを使用するかです。これらのすべてが今やトランジションをトリガーします。とてもクールです。
デフォルトでは、ビュートランジションのデフォルトCSSアニメーションである滑らかなクロスフェードを使用していますが、ビュートランジションの疑似セレクタを使用してアニメーションの実行方法を定義できます。ここでは、view-transition-old * { animation: 300ms fade-out }、view-transition-new * { animation: 300ms fade-in }というCSSを設定しています。
startTransition、useDeferredValue、またはsuspenseFallbackからContentへの切り替えなどのアニメーショントリガーによってDOMが更新されると、Reactは宣言的なヒューリスティックを使用して、このアニメーションに対してどのビュートランジションをアクティブ化すべきかを自動的に決定します。
つまり、DOMと仮想DOMを使用して、どのトランジションがラップされ、どの状態間で変更されたかを確認し、その時点でそれらのアニメーションをトリガーします。
このような機能がクールなのは、舞台裏では大量の作業があり、Reactにこのように組み込むのは本当に複雑だということです。しかし、実際に使ってみると、ネイティブブラウザAPIのように感じます。なぜならそれはネイティブブラウザAPIだからです。ReactはネイティブブラウザAPIとうまく連携するために多くの変更を行いましたが、彼らはそれを実現し、それは機能し、素晴らしいです。
そうですね、きれいなフェードが見えます。クリックするとものが切り替わるだけでなく、次のページにフェードするのが見えます。これを非常に簡単に実現するには、メインボディコンポーネントの周りにビュートランジションをラップし、URLがスラッシュならホーム、そうでなければ詳細というロジックを設定します。これがアプリにビュートランジションを追加する複雑さのすべてです。VDOMで変換して変化できるものをラップするだけで、要素間でトランジションするようになります。
T3チャットにこれを追加することにとても興奮しています。通常はアニメーションが好きではありませんが、これは正しい方法です。
ビュートランジションを配置する場所に関する良い指摘がありますが、Suspenseラッパーと同様に複雑さがあります。しかし、これはSuspenseラッパーよりもはるかに簡単に理解できます。なぜなら、間違った場所にビュートランジションを配置すると、アプリが正しくトランジションしていないことがわかるからです。ありがたいことに、どのビュートランジションにも追加できるデフォルトのnoneがあるので、条件付きでカスタマイズできます。非常に良いことです。
また、ビュートランジションに特定の文字列名を設定し、CSSを通じてそれをターゲットにすることもできます。そして、その変更により、クロスフェードが遅くなりました。アニメーションCSSを500に上げたため、実行に時間がかかるようになりました。これを50に変更できますか?できます。そして、それは機能します。とてもクールです。
見るには少し低すぎるので、少し見えるように150にします。実際にはそれが好きです。それは控えめですが、切り替えがそれほど不自然ではなくなります。正直に言って、30fpsのビデオではこれを見るのは難しいでしょう。これで遊びたい場合は、説明欄にリンクがあります。かなりクールです。
ページのコンテンツだけをトランジションさせるなら一つのことですが、ビュートランジションが本当にクールになるのは共有要素です。Neanのブログで見たように、タイトルが別の場所に移動します。なぜならその要素はまだそこにあり、ページ上の別の場所にあるだけだからです。ビュートランジションを使用すると、これも可能です。
一意の名前を付けます。この「name」という命名が好きではありませんが、識別子やIDなどの方が良いと思います。しかし、これが何であるかを確立すると、このビュートランジションがこの識別子を持つものに対するものであることがわかります。次のビューにも同じ識別子がある場合、実際に見せた方が良いでしょう。結果はとてもクールです。
ビデオをクリックしたときに何が起こるか見てください。これが最もクールなことではないと言ってみてください。以前は、これを実現するコードを書くのがどれほど面倒だったか知っていますか?ナビゲーション時に要素を移動させるコードを書くのがどれほど面倒だったか知っていますか?今では、このために書く必要があるコードはすべてここにあります。
識別子付きのビュートランジションをラップしたサムネイルコンポーネントがあります。ビデオコントロールとビデオがあり、ビデオはサムネイルコンポーネントを使用しています。また、同じサムネイルコンポーネントを使用するリストビューもあります。識別子は常に同じで、カスタムJSは書かれていません。IDを持つラッパーコンポーネントだけで、アプリにこのような素晴らしいトランジションを追加するのに必要なすべてです。
非常に異なるものも処理します。例えば、ビデオの高さがほぼ同じ場合、正しいことを行い、スペースを埋めるために微妙に拡大します。しかし、下部近くのものをクリックすると、上に移動します。これはセットアップが容易ではありません。これはとても嬉しいです。とてもクールに見えます。
デフォルトでは、Reactはトランジション用にアクティブ化された各要素に一意の名前を自動的に生成します。Reactが、名前付きのビュートランジションが削除され、同じ名前の新しいビュートランジションが追加されるトランジションを検出すると、共有要素トランジションをアクティブ化します。
彼らはアニメーションの原因も持っているので、トランジションのタイプを制御できます。前進ナビゲーションと後退ナビゲーションで異なるトランジションが必要な場合は、addTransitionTypeヘルパーを呼び出し、異なるケースを設定できます。shareOnNavForwardではforward、backではbackwardにスライドさせたいときはそうします。
これでトリガーしたトランジションタイプに応じて異なるアニメーションが表示されます。そして明らかに、CSSでビュートランジションターゲットを使用してこれを適用できます。oldはトランジション前の状態、newはトランジション後の状態です。特定の識別子を持つ共有の特定のクラスをこのようにターゲットにできます。
これは非常にシンプルであり、これはすべてCSSだけで実現しています。実際のブラウザ標準を使用してこれをすべて行っています。Reactチームがクレイジーな新しいアニメーションシステムを構築する代わりに、ブラウザ標準に大きく依存してくれたことにとても感謝しています。
この変更により、トップナビがものに移動するときに左にスライドし、離れるときに右にスライドするのが見えます。とてもクールです。これが今こんなに簡単になりました。SafariやChromeなど、それをサポートするブラウザを使用している限り。はい、Firefoxはもっとがんばってほしいですね。
前述のように、Suspenseもビュートランジションをアクティブにするので、これもとてもクールです。コンテンツが入ってくる前に何かのフォールバックがある場合、それをアニメーション化できます。Suspenseをビュートランジションでラップするだけで、このようなことをすると、プレースホルダーからコンテンツへの素敵なアニメーションが表示されます。
そして、Suspenseの仕組みのおかげで、それはレンダリングされたままです。この小さなアニメーションがいかにシンプルで素敵か見てください。彼らはそれに多くの作業を入れる必要もありませんでした。CSSだけで、新しいキーフレームを追加するだけで、それは機能します。とてもクールです。
フォールバックにexitを、コンテンツにenterを提供することで、カスタムアニメーションも提供できます。ここでは、終了時にスライドダウンし、入力時にスライドアップするよう指定できます。CSSを書くだけで、これら2つの異なるケースを処理します。もう一度サンドボックスで遊ぶと、コンテンツが上にスライドするのが見えます。とてもクールです。そして、終了はフェードが下に行きます。ロード中の待機時の奇妙なグレーアウトフェードが下に行き、新しいコンテンツがそれを置き換えるために上に行きます。
また、ビュートランジションを使用して、リストのアイテムが並べ替えられるときにアニメーション化することもできます。とても良いですね。Reactでリストを扱う時と同じように、キーを入れるだけです。
「third」と入力してみましょう。冗談ですか?それすらも知りませんでした。とてもクールです。ここでは特別なものは何も書かれていません。これはリストから削除される項目を処理するためのクレイジーなJSコードではありません。ビデオコンポーネントにビュートランジションラッパーを1つ追加しただけで、deferredValueヘルパーを使用してフィルタリングすると、正しいタイミングでフックできるようになります。それだけです。
ここでようやくdeferredValueの価値が分かります。検索テキストをこのコンポーネントに渡すと、最初のレンダリングで以前のものを使用し、変更されるとその変更が来ることを知り、ビュートランジションをトリガーします。次に新しい状態をレンダリングし、それにトランジションします。とても良いです。
しかし、このdeferredValueラッパーはReactに「この値が変更されると、2つの状態があります。遅延バージョンと新しいバージョンです。トランジションをトリガーしてください」と伝えます。これは文字通り2行のコード変更で、以前はブラウザのパフォーマンス混沌に関する博士号を必要とし、さらにコードベースの動作方法を台無しにしていたものを追加するものです。とても良いです。とても興奮しています。
これはSeb Markbの「赤ちゃん」でした。彼はサーバーコンポーネントの人なのにクレイジーですが、ビュートランジションを実現したかっただけで、彼はそれを実現するために全力を尽くしました。彼のために興奮しています。これはとてもクールなことです。
そして、これがここで話しているすべてだったとしても、私は興奮していたでしょうが、さらに進んでいます。だから、アクティビティについて話す必要があります。
過去のアップデートで、コンポーネントを視覚的に非表示にして優先度を下げ、アンマウントやCSSによる非表示と比較して性能コストを削減してUIの状態を保持することを可能にするAPIを研究していることを共有しました。
過去にはDOMから削除されるときに要素の状態を保持するためにポータルを使用するなど、多くのハックを行ってきました。それは面倒でした。今では、そのための組み込みコンポーネントがあります。
アクティビティは、UIの一部を表示および非表示にするための新しいコンポーネントです。アクティビティが表示されているときは通常通りレンダリングされます。非表示の場合はアンマウントされますが、状態は保存され、画面上の表示されているものよりも低い優先度で引き続きレンダリングされます。
これがどれほど役立つか分かりますか?入力ボックスがあり、UIの別の場所に切り替えて別のページに移動し、戻った場合、その入力ボックスの状態は保持されます。カウンターコンポーネントがあり、間違ったタブに移動して、ボタンだと思っていたものがリンクだったとクリックして戻っても、それはまだそこにあります。
チャットがすでに理解していますね。基本的には逆ポータルです。これは素晴らしいことです。本当に素晴らしいです。
ローカルストレージ、条件付きレンダリング、CSSによる非表示化、仮想DOMがそれを気にして他の要素から優先度を奪うことなど、すべての混沌に対処することなく、要素をレンダリングしてその状態を所有できるようになりました。
メインUIをブロックせずに可能な限り早くレンダリングを開始したい重いものがある場合、今すぐそれを行うことができます。そして、他の人も気づいているように、React Routerはこれで大いに楽しむことができるでしょう。絶対に同意します。ルーターは次のページでどのHTMLがあるかを知るだけでなく、そのためのReact構造も完成させることができるという、クレイジーなことができるようになります。これでルーティングでクレイジーなことができるようになります。とても興奮しています。
ここで指摘される主要な注意点の1つは、アクティビティが非表示の場合、エフェクトはマウントされないということです。アクティビティでラップされたコンポーネント内にuseEffectがある場合、そのコンポーネントが非表示の場合、useEffectは実行されません。状態は保持されますが、エフェクトは実行されません。アクティビティを表示から非表示に切り替えると、エフェクトはクリーンアップを行います。そのため、return cleanupは実行されますが、アクティビティの内部にあるときは実行されません。
これがそれがとてもパフォーマントである理由の一部です。巨大で非常に重いものをアクティビティでレンダリングし、それを非表示のままにしておいても、パフォーマンスに意味のある影響はありません。
チャットがこれに気づいていて嬉しいです。トランジションに最適ですね。「くそ、Reactをまた使い始めないと」。事前レンダリングだけでなく、インスタントなブラウジング履歴のためにも最適です。本当にクールです。とてもクールです。
彼らの例を見てみましょう。アクティビティによる状態の復元です。ユーザーがページから離れるとき、古いページのレンダリングを停止するのが一般的です。はい、これはReactのほとんどすべてのルーターの動作方法の一つです。だからこそ、ナビゲーションでそれを失うのでURLに状態を入れるよう人々に伝えるのです。
しかし、彼らが言うように、ユーザーが古いページに戻ると、以前の状態は失われます。homeに入力フィールドがあり、ユーザーがページを離れて入力がアンマウントされると、彼らが入力したテキストは消えます。アクティビティを使用すると、そのようなものの可視性を変更できます。
これでhomeは「/」にいる場合に表示され、そうでない場合は非表示になります。そのため、まったくレンダリングされませんが、まだ存在するので、その状態は保持されます。
ここに例があります。ビデオを検索してみましょう。「f」と入力し、「fourth」に移動して、戻ると、それはまだその状態にあります。以前はこのようなことを行うのがどれほど面倒だったか知っていますか?
チャットも理解していますね。「クエリパラメータやsportパラメータなしのダッシュボード上の永続的なフィルター」、「roundestでの画像キャッシュのためのハック」です。そうです、それははるかに簡単です。次の画像を取得するだけです。とても良いですね。
人々はこのような素晴らしい変更に興奮しています。CSSによる非表示化の問題を上部で指摘しています。CSSで非表示にする問題は、ブラウザがHTMLを生成してページに配置し、その後非表示にするためにまだ多くの作業を行う必要があることです。また、他の要素にも影響します。
アクティビティはCSSでの非表示化で使用するブラウザの機能をすべて使用するだけでなく、コンポーネントが実際にそこにない場合に実行する必要のないものを無効にしているため、Reactのすべてを使用していません。そうです、コンポーネントが表示されるまでフックは実行されません。とても良いです。これは大きな変更です。
UIのすべてをアクティビティでレンダリングし、アクティブ化するとはるかに速く表示され、状態はすべて維持されます。React Routerで何かをラップしてパフォーマンスを確認するのを見てみたいです。RAMの使用量がどうなるか非常に興味があります。「これだけのRAMがあるので何かに使う必要がある」。フロントエンドをたくさん扱っていなくても、これがOPであることがわかります。
ちなみに私の経歴はバックエンドです。皆さんを私と同じようにフロントエンドに興奮させようとしているだけです。私の歴史はすべてバックエンドで、Reactには比較的遅く参入し、彼らが行っているすべてのクールなことに恋をしました。その愛と興奮を共有しようとしているだけで、皆さんがそれを見て理解していることに興奮しています。
これらすべてがいかに優雅に組み合わさっているか見えますか?異なるページ間のトランジション、状態の保持、タイプするときのアニメーション。これは通常必要とされるようなクレイジーなカスタムJSではなく、組み込みのブラウザプリミティブと組み込みのReactコアの機能を使用しているだけの単純なコンポーネントラッパーです。とてもクールです。
以前は他のフレームワークがReactよりもアニメーションが優れていました。そうでないとは言いません。追いつくのに時間がかかりすぎましたが、Firefoxユーザーでない限り、彼らは飛躍していると感じます。(Zenで泣く)まあそういうものです。
いずれにせよ、私が示唆していたように、これを使って事前レンダリングも行うことができます。ここでは特定のページ(details/1など)を事前レンダリングして、より速くレンダリングできるようにしています。
彼らが言っていることは:「ユーザーが使用する可能性が高いUIの次の部分を、使用する準備ができる前に事前に準備しておきたい場合があります。これは、次のルートがレンダリングに必要なデータでサスペンドする必要がある場合に特に役立ちます。ユーザーがナビゲートする前にデータが既にフェッチされていることを確実にするのに役立ちます。例えば、現在のアプリでは各ビデオのデータをロードするためにサスペンドする必要があります。選択したときに、すべてのページを非表示のアクティビティでレンダリングしてユーザーがナビゲートするまで待つことで、これを改善できます。」
ここではすべてのビデオをマッピングして、非表示のアクティビティですべてレンダリングしています。これにより、すべてがフェッチできるようになります。一つに移動すると、すでにデータが用意されています。待つ必要がありません。すべてを行うことができ、ここでもクレイジーなカスタムコードは書かれていません。
詳細を見ると、サスペンスはまだあります。サスペンスはアクティビティ中に解決できます。とてもクールです。エフェクトは実行されませんが、サスペンスバウンダリを通じたデータフェッチは実行されます。
ここではビデオデータを取得するためにuseCallを使用しています。これはサスペンドをトリガーするので、アクティビティでサスペンスが発生し、コンポーネントはレンダリングされ、DOMで何かを行う必要なく準備できます。その後レンダリングするだけです。信じられないほど単純です。ここにはクレイジーなトランジションやアニメーションコードはどこにもありません。ビュートランジションでものをラップするだけで、ほぼ完了です。
これはFacebookがRelayを愛している状況に似ています。Facebookは、グラフ理論の博士号なしでウェブアプリのパフォーマンスを向上させるために、Relayの優れた部分をフィルタリングすることに多くの時間を費やしています。これはRelayを超えた3層の蒸留物であり、小さな利点を見つけてブラウザ標準と積み上げることで、誰もが恩恵を受けられるものを作っています。
これはサーバーコンポーネントではないと言いましたが、ここで言及されています。SSRとアクティビティについて:「SSRを使用するページでアクティビティを使用する場合、追加の最適化も可能です。ページの一部がmode=”hidden”でレンダリングされる場合、それはSSRレスポンスに含まれません。代わりに、Reactはページの残りの部分がハイドレーションされている間、そのアクティビティ内のコンポーネントのクライアントレンダリングをスケジュールし、画面上の表示されているコンテンツを優先します。」
これで「クイック・アット・ホーム」を実現しました。サーバーで何かを行わないように、初期レンダリングをブロックせず、クライアントでの再レンダリングを優先するようにReactに伝えることができるようになりました。とてもクールです。そして、同じプリミティブを使用しています。特別な「ハイドレートする/しない」というものではなく、クライアント側で直感的に使用するのと同じ方法でアクティビティを使用すると、サーバーでも機能します。
これが私がReactを好きな理由です。他のフレームワークよりも動きが遅いですか?はい、それは彼らが問題が十分に似ている場合に複数の問題を一度に解決するために使用できる適切なコアプリミティブを見つけようとしているからです。
サーバーレンダリングでの最初のバイトをどのようにブロック解除するか、クライアント上で何をレンダリングするかを優先する方法、そして表示されていないときにクライアント上でバックグラウンドで物事をレンダリングする方法、これらはすべて直感的には異なることを行うと予想される複雑な問題です。しかし、このチームの天才的なところは、彼らが重複を見つけるために戦い、これらの問題をすべて1つのエレガントな方法で解決するものを構築することです。それは本当にクールです。
常にエレガントというわけではありません。useEffectのすべての奇妙な引数を見てください。しかし、時にはそうであり、これは本当にエレガントに見えます。これで遊ぶのがとても楽しみです。
ここで最もクールな部分の1つは、Reactがアクティビティ内のコンテンツのハイドレーションを優先度を下げることです。サスペンスコンテンツが低い優先度でハイドレーションされるのと同様です。ユーザーがページと対話すると、必要に応じてバウンダリ内のハイドレーションを優先します。
将来のアクティビティモード:「将来的にはアクティビティにより多くのモードを追加するかもしれません。例えば、一般的なユースケースはモーダルをレンダリングすることで、アクティブなモーダルビューの背後に以前の非アクティブなページが表示されています。hiddenモードはこのユースケースには機能しません。なぜならそれは表示されておらず、SSRに含まれていないからです。代わりに、コンテンツを表示したままSSRに含め、更新のためにアンマウントしたまま優先度を下げる新しいモードを検討しています。」
これは、フルスクリーンモーダルが開いているときに、背景が完全に更新される必要がないという点で理解できます。このケースがそれ自体のモードを必要とするほど一般的かどうかはわかりませんが、バックグラウンドコンテンツをブロックするモーダルのような実際のユースケースを考慮していることは素晴らしいことです。Chromeがこのようなことを考慮し始めるのに数十年かかりました。
これで、近い将来(おそらくReact 20、あるいはもっと早く)にメインのReactバージョンに確実に導入される予定の、実験的機能の紹介は終わりです。私はこれらをたくさん試してみる予定ですが、ここにはもっと多くのことがあります。そのIDEプラグインも含めてさらに詳しく見ていきましょう。
彼らは、ソリューションを試した後、変更や削除することが多いと指摘しています。彼らが取り組んでいるソリューションが早すぎると共有されると、コミュニティに混乱と錯綜を引き起こす可能性があります。透明性を保ちながら混乱を制限するために、特定のソリューションを共有せずに、現在ソリューションを開発している問題を共有しています。
そのため、これらはまだ試すことのできるものではなく、特定のソリューションを約束しようとしているわけではありません。彼らはまだ明確な答えを持っていないので、あまり期待しないでください。並行モードのようなことを再び起こしたくないのです。それは災害でした。
これが自動的に150のフェッチを開始することはないと思います。なぜなら利用可能でないときにアクティビティを優先度を下げるからです。それが重要なポイントであり、オプションです。アクティビティ内に多すぎる要素がある場合、Reactスケジューラーは隠れたアクティビティ内のすべての要素の優先度を下げることを十分賢く行うでしょう。間違ったものを選ぶかもしれませんが、確実に優先度を下げます。ただし、これがスケールでどのように見えるか見るのが楽しみです。
優先度を下げるということは、もし何かを行わず、通常通りナビゲートすると、以前と同じように動作するということです。したがって、RAMやCPU、ネットワークなど、それを行うのに必要なものすべてを持っているなら、クールにそれを行うことができ、それらのものをレンダリングできます。しかし、入力やアクティビティではないページ上の他のコンテンツなど、他のものが多すぎて優先順位が高い場合、それが取られます。
これについてさらに:「検討しているもう一つのモードは、メモリの使用量が多すぎる場合に非表示のアクティビティの状態を自動的に破棄する機能です。コンポーネントがすでにアンマウントされているため、アプリの最近使用されていない非表示の部分の状態を破棄する方が、リソースを消費しすぎるよりも望ましい場合があります。」はい、とても素晴らしいです。
パフォーマンスツールについても見ていきましょう。パフォーマンスを特定するためのより多くの方法が必要です。友人のAidenをご存知かもしれません。Sameの作成者として知られていますが、主にmillionjsとReact Scanで知られています。私の「Reactは本当に遅いのか」などの最近の動画で、React Scanの力を深く見ることができます。彼は何をしているのかよく知っています。Reactのための非常に有用なパフォーマンスツールを多く構築してきました。
今、Reactチームも追いつき始めていて、それは非常に遅れていましたが、それを見るのはとても嬉しいことです。「私たちはブラウザAPIを使用してパフォーマンスプロファイラにカスタムトラックを追加し、アプリのパフォーマンスに関する詳細情報を提供する新しいカスタムトラックのセットに取り組んでいます。この機能はまだ進行中であり、ドキュメントを公開したり、実験的機能として完全にリリースする準備ができていません。Reactの実験的バージョンを使用すると、プロファイルに自動的に追加されるパフォーマンストラックのスニークプレビューを見ることができます。」
ここでは、レンダリングがいつ始まるかを示すためにReactコードで定義できるカスタムトラックが表示されています。これにより、ReactのChromeエクステンションと通常のパフォーマンスタブの両方でのReactパフォーマンス関連のツールの使用が大幅に簡単になります。
これはChromeチームと並行して行われている作業で、パフォーマンスタブをより便利にするためのものであり、それは非常に必要とされています。なぜなら最近このタブで多くの時間を過ごしており、それは厳しいものだからです。非常に便利で、非常に悪く、私たちは可能なすべての助けを必要としています。いくつかのバグがあるので、まだ完全に準備ができていません。彼らはまだフィードバックを収集しているので、これを使用してフィードバックがある場合は、彼らに知らせてください。それが彼らがこれを行っている理由です。
もう一つ私がとても興奮しているものがあります。こんにちはSolidJS、ついに追いついてきました。自動エフェクト依存関係です。「私たちはフックをリリースし、3つの動機がありました:コンポーネント間でコードを共有する、ライフサイクルではなく関数の観点で考える、そして事前コンパイルをサポートすることです。最初の2つは素晴らしく達成しましたが、3つ目はそれほど役立ちませんでした。
リリース以来、フックはコンポーネント間でコードを共有するのに役立ってきました。現在、フックはコンポーネント間でロジックを共有するためのお気に入りの方法であり、レンダープロップスや高階コンポーネントのユースケースは以前よりも少なくなっています。また、フックは、ライフサイクルが従来のクラスコンポーネントに深く埋め込まれていたため不可能だったfast refreshのような機能をサポートするのにも成功しています。現在、それらのタイプのことを行うのははるかに簡単です。」
私は今やfast refreshなしの生活は想像できません。本当に素晴らしいです。保存してすぐに変更が表示され、状態が失われません。
残念ながら、一部のフックはまだ難しいです。「エフェクトは関数として考えるのではなく、ライフサイクルとして考えるのが難しいです。エフェクトは異なるものでトリガーされる関数ですが、それらはコンポーネントのライフサイクルではなく、データのライフサイクルです。コンポーネントのライフサイクルでもトリガーされますが(アンマウント時など)、それは混乱します。
特にエフェクトは理解するのが難しく、開発者からよく聞く一般的な痛みポイントの一つです。昨年、私たちはエフェクトが実際にどのように使用されているか、そしてそれらのユースケースがどのように簡素化され、理解しやすくなるかを研究するために多くの時間を費やしました。多くの場合、混乱は実際に必要のないときにエフェクトを使用することから来ていることがわかりました。」
「You Might Not Need an Effect」ガイドは、エフェクトが正しいソリューションではない多くのケースをカバーしています。まだこのブログ記事を読んでいないReact開発者の方は、ぜひ読んでみてください。素晴らしい記事で、エフェクトを実際に使用すべきでない場所を学ぶのに非常に役立ちます。
これは本当によくあるケースです。姓名を結合するようなものをエフェクトで行い、どちらかが変更されるたびに新しい状態に設定します。単にそれをインライン化してください。これを計算するのは非常に安価なので、レンダリング中に行うだけです。
ここで言われているように、「エフェクトが問題に適していても、エフェクトは過去のクラスコンポーネントのライフサイクルよりも理解するのが難しい場合があります。混乱の理由の1つは、開発者がデータとエフェクトが実際に何をしているかというエフェクトの視点からではなく、ライフサイクルのようなコンポーネントの視点からエフェクトを考える傾向があると考えています。」
例を挙げると、接続を作成し、roomIDで接続し、roomIDが変更されたときに切断を返します。roomIDが変更されると、そのルームから切断して新しいルームに接続したいからです。
多くのユーザーはこのコードを「マウント時にroomIDに接続し、roomIDが変更されるたびに古いルームを切断して接続を再作成する」と読みますが、これはまだコンポーネントの視点から考えています。つまり、エフェクトを正しく書くためにはすべてのコンポーネントのライフサイクル状態を考える必要があります。これは難しいことがあります。
コンポーネントの視点から見た場合、エフェクトがクラスのライフサイクルよりも難しく感じるのは理解できます。このフレーミングに完全に同意します。Reactモデルで人々が持つ最大の問題の1つは、コンポーネントを考えすぎて、データフローを考えすぎていないことです。フックの美しさは、ライフサイクルがもはやコンポーネントの周りにないことです。ライフサイクルは代わりに、フックに渡されるデータの周りにあります。
私はこれを関数対コンポーネントとしては考えませんでした。データライフサイクル対コンポーネントライフサイクルと考えましたが、彼らがどのように表現するか興味があります。
依存関係のないエフェクト:「その代わり、エフェクトの視点から考える方が良いです。エフェクトはコンポーネントのライフサイクルを知りません。同期を開始する方法と、必要に応じて停止する方法だけを記述します。ユーザーがこの方法でエフェクトを考えると、エフェクトは書きやすく、必要に応じて何度でも開始・停止するのに強くなる傾向があります。
私たちはエフェクトがコンポーネントの視点から考えられる理由を研究し、その理由の1つは依存配列だと考えています。それを書かなければならないので、それはそこにあり、あなたが反応しているものを思い出させ、「値が変わったときにこれを行う」という心理モデルに誘導します。
フックをリリースしたとき、私たちは事前コンパイルでそれらをより使いやすくできることを知っていました。Reactコンパイラにより、ほとんどの場合、useCallbackとuseMemoを自分で書かなくても済むようになります。エフェクトに関しては、コンパイラがあなたのために依存関係を挿入できます。」
つまり、初めて、エフェクトに配列を渡さないという本当のユースケースが存在することになります。なぜなら現時点では全く意味がありませんが、将来的には実際に意味を持つかもしれません。
このコードでは、Reactコンパイラがあなたのために依存関係を推測し、自動的に挿入できるので、それを見たり書いたりする必要がありません。IDEエクステンションやuseEventEffectのような機能により、デバッグまたは最適化のために依存関係を削除する必要がある場合に、コンパイラが挿入したものを表示するコードレンズを提供できます。
これは、エフェクトを書くための正しいメンタルモデルを強化するのに役立ちます。エフェクトは、コンポーネントやフックの状態を他のものと同期させるために、いつでも実行できます。
useEventEffectはuseCallbackに似ていますが、変更されることはありません。実質的には、参照に関数を詰め込むのと同じことです。訪問バインディングが変更されると、エフェクトが再実行されてしまいますが、それは望ましくありません。
これにより、コンポーネントがアクセスできるデータに関数をバインドできますが、意図しない場合に更新をトリガーする必要はありません。非常に便利で、エフェクトの変更をトリガーすべきではない依存関係が多く渡されるのを避けることができます。
ここでは、アイテム数でエフェクトをトリガーしたくなく、URLだけでトリガーしたいので、visitedUrlとnumberOfItemsを使用するためにイベントエフェクトを切り離します。これをすべてここに持ち、onVisitをuseEffectに渡すだけで、同じクロージャ内にあるためです。これで、アイテム数の変更時にはエフェクトが実行されなくなります。とても良いですね。
これが出荷されるまでに時間がかかりすぎました。皆さんに完全に同意します。まだ正式に出ていませんが、それが消えていないことに非常に興奮しています。実際に出荷されています。
彼らが検討していた別のuseEffect関連のものがありました。useResourceEffectです。伝説のLaurenがこれに取り組んでいました。useResourceEffectは似ていますが、クリーンアップ付きのオブジェクトまたはデータを提供します。これは永遠に必要としてきたものです。
Dan Abramovとやり取りした古いスレッドがあり、時にはものをインスタンス化して、常に2回実行されないクリーンアップを持つ必要があることを説明しようとしていました。それを彼らに伝えるのはとても難しかったです。「今書かなければならない4つのフックはこれで、本当に書くべきフックは1つだけです。」彼らはある程度理解しましたが、実現しませんでした。しかし、彼らはその方向に向かっています。
彼らはエフェクトをより単純にするために欠けているピースを追加しているので、私たちがそれらを理解しやすくなり、暴走してコードを破壊する可能性が低くなります。そして、これからお話するIDEエクステンションと組み合わせると、「ここにあるこのものは、このエフェクトが常に実行される原因になるかもしれないので、イベントエフェクトに移動してエフェクト内で呼び出される関数にしたほうがいいかもしれません」と言ってくれます。
彼らが投稿で言うように:「私たちの希望は、依存関係を自動的に挿入することが書きやすいだけでなく、エフェクトが何をするのかという観点から考えさせることで理解しやすくすることです。コンポーネントのライフサイクルではなく。」この変更にとても興奮しています。長い間それを回避してきました。
IDEエクステンションを見てみましょう。Reactコンパイラは現在RCにあります。RCRCというのは少し面白いですが、Reactコンパイラはほぼ準備ができています。MetaとFacebookではほぼすべてに使用されており、T3チャットでも使用しています。私たちにとって救世主となっています。彼らは今後数ヶ月でコンパイラの最初のセマンティックバージョンの安定版を出荷するために懸命に取り組んでいます。とても素晴らしいです。
コンパイラが公式に10sever stableになることにとても興奮しています。彼らの安定性の基準は非常に高いですが、私は現在構築しているすべてのものでそれを使用しており、非常に良い結果を得ています。
しかし、コンパイラの取り組みは単に「Reactコードを高速化できる」だけではなく、エコシステム全体をよりよく統合する方法でもあります。そのうちの一つがIDEです。
「私たちはReactコンパイラを使用して、コードの理解とデバッグを向上させる情報を提供する方法を模索し始めました。一つのアイデアとして、React Compでのローレンのトークで使用されたものと同様の、Reactコンパイラによって動力を得た新しい実験的なLSPベースのReact IDEエクステンションの探索を始めました。」
これは基本的に、コンパイラがコンパイルしたものを表示します。コンポーネントやフックがコンパイラによって最適化されたかどうかを知る一つの方法は、上部にこの小さな「$」変数を探すことです。このように使用する方法を心配する必要はありません。直接使用するためのものではなく、実際にはコンパイラのためのものです。
これを考える一つの方法は、コンパイラが値を効率的にキャッシュおよび取得するために使用できる大きな配列です。これはとてもクールです。
私がコンパイラについて人々が持つ最大の懸念の一つは、出て行くコードを人々が理解しにくくなることです。ほとんどの開発者は入っていくコードすら理解していないと思います。彼らはただ自動補完をしているだけで、Reactを最適化したりメモ化する方法を理解するほどReactを十分に理解していません。そのため、彼らにとってはnoopであり、単により良いコードを出力するだけです。
しかし、深く気にする人々、このようなチャンネルを見て、実際にReactを使用する方法をチームに教えようとしている人々にとって、これは私たちにとって大きなことです。なぜなら、Reactコンポーネントから何が出てくるかを見ることができ、コンパイラがどのように機能し、他の作業とどのようにインターフェースするかを理解するのがはるかに簡単になるからです。コンパイラ出力を単にホバーして見ることができれば。
しかし、エクステンションは私たちがここで見ているものよりもはるかに進んでいます。ここに他の深い例があるかどうか覚えていません。
これは楽しい例です。Reactコンパイラのeslintルールははるかに優れています。「refのcurrentプロパティはレンダリング本体中にアクセスできません。」これはローレンが取り組んでいるものの早期プレビューです。ちなみに彼女は絶対的な魔術師です。彼女の仕事をご存知でなければ、Twitterでフォローできる最もユーモアのある人の一人でもあります。「potatoes」というスペルです。Reactコンパイラでの「forgive and forget」は素晴らしい言葉遊びです。なぜならそれは以前は「react-forget」だったからです。RCはリリース候補であり、これはReactコンパイラRCではありません。彼女は自分自身を止められず、ミーマー(ミーム作成者)です。私たちはローレンが大好きです。
とにかく、IDEエクステンションについて、彼女が考えていることについて少し話しました。それは本当にクールです。「私たちのアイデアは、コンパイラの静的分析を使用して、IDE内で直接より多くの情報、提案、および最適化の機会を提供することです。例えば、Reactのルールに違反するコードの診断を提供したり、コンポーネントとフックがコンパイラによって最適化されているかどうかをホバーして表示したり、自動的に挿入されたエフェクトの依存関係を見るためのコードレンズを提供したりできます。IDEエクステンションはまだ初期の探索段階ですが、今後のアップデートで進捗状況を共有します。」
自動エフェクトの依存関係のためのコードレンズはとても素晴らしいです。言語がこれを行うのと同様に、例えばRustはLSPでこれを行います。何かを入力すると、実際に何であるか、何をするかを示す背後の灰色のテキストが表示されます。または、GitHubとgit lensプラグインでは、ここで灰色のテキストが表示され、これがGeminiの動作を修正しようとした時だと示しています。
エフェクトがすべての依存関係を書くのではなく、どの依存関係を持っているかを示すのにそれを持つことは非常にクールです。とても興奮しています。Reactに入る全ての変更にとって大きな勝利となるでしょう。Reactチームがより全体的に考えていくのを見るのは素晴らしいことです。
Reactは、UIの更新方法を変更するために追加するJSライブラリから、あらゆる規模のチームのための巨大なアプリケーションを構築するためのツールスイートへと進化しました。IDEの統合はその素晴らしい例の一つです。私たちが書いているコードはあまり変わらないかもしれませんが、それを書く体験の質は常に向上しています。
これがますますReactの焦点となっていくのを見ることになると思います。新しいAPIを導入することや、Reactを書く新しい方法を考えることではなく、Reactの構文を根本的に変更するようなフックの瞬間は二度とないでしょう。代わりに、そこにあるべきではなかった構文を削除し、コードをできるだけシンプルにするものを見ることになるでしょう。それによって、人間とAIが協力して物事をより効果的に出荷できるようになります。はい、AIをどこかで言及しなければなりませんでした。ここまで来ました、大丈夫でしょう。
とにかく、ラップアップする前にもう少しクールなことがあります。フラグメント参照です。「DOM APIの多くは、イベント管理、位置決め、フォーカスなどのためのものですが、Reactで書くときは構成が難しいです。これはしばしば開発者がエフェクトに頼ったり、複数の参照を管理したり、findDOMNodeのようなAPIを使用したりする原因となります。」
それを経験し、二度とやりたくありません。「私たちは、単一の要素ではなく、DOM要素のグループを指すフラグメントへの参照を追加することを検討しています。これにより、複数の子要素の管理が簡素化され、多くのランダムなDOM APIを呼び出さなくても、構成可能なReactコードを書きやすくなることを希望しています。フラグメント参照はまだ研究中です。最終的なAPIに近づいたら、より多くの情報を共有します。」
これはT3チャットの入力フィールドの管理に多く使用できて嬉しいです。
話していたように、ジェスチャーアニメーションについても:「ビュートランジションを拡張して、メニューを開くためのスワイプや写真カルーセルをスクロールするなどのジェスチャーアニメーションをサポートする方法を研究しています。」Ken Wheelerにシャウトアウト、知っている人はわかりますね。
「ジェスチャーはいくつかの理由で新しい課題を提示します。ジェスチャーは連続的です。スワイプすると、アニメーションは完了まで実行されるのではなく、指の位置に時間的に結びついています。Reactはこれが得意ではありません。Reactは部分的なものが得意ではありません。Reactは前と後を取り、その間を効率的に処理します。フレームごとに変化するものは得意ではありません。それはReactがやることではありません。ReactはCSSを使ってそれをやれと言います。しかしジェスチャーはそれを必要とし、ここで適切なバランスを見つけることは本当に難しいでしょう。彼らがそれをそうでないと装っていないのが好きです。」
彼らが言うように、ジェスチャーは連続的であり、完了しません。それは単に始まって終わるというようなシンプルなものではありません。指を離したとき、ジェスチャーアニメーションは完了まで実行されるか、どれだけ進んだかによっては元の状態に戻ることがあります。例えば、メニューを部分的にしか開かなかった場合など。これは複雑であり、Reactのモデルはこれにうまく対応していません。
また、「ジェスチャーは古いものと新しいものを反転させます。アニメーション中は、アニメーション元のページを生きたまま対話可能にしておきたいです。これはブラウザのビュートランジションモデルを反転させます。古い状態はスナップショットであり、新しい状態はライブDOMです。古い状態が生きたままであることでこれははるかに複雑になります。」彼らへの同情を表します。これをどうやって実現するか解決してほしいです。
「私たちはうまく機能するアプローチを見つけたと信じており、ジェスチャートランジションをトリガーするための新しいAPIを導入するかもしれません。今のところ、ビュートランジションの出荷に集中しており、その後ジェスチャーに再訪する予定です。」
トランジションの話題に関連して、こんにちはMiles。彼は最近特に甘えたがっています。私は2回旅行に行ったので、彼は欲しい注目を得ていません。だから常に甘えてきます。肩に乗りたいようですね。彼の爪を切ったばかりなので、いつもより少し短くなっています。彼は今私によじ登るのに少し緊張していますが、肩は彼のお気に入りの場所です。やあ、バディ。わかっています。すぐにもっと一緒に過ごしましょう。でも今は撮影を終わらせる必要があります。それでいいですか?肩の上で動画を終わらせましょう。
まだ何が残っていますか?並行ストアです。「React 18を並行レンダリングでリリースしたとき、useSyncExternalStoreもリリースしました。Reactで最もクールで壊れやすいAPIの一つです。これは並行レンダリングを全くサポートしていません。サポートすることはできますが、ストアが更新されるたびに同期レンダリングを強制することでそれを行います。これはクールですが、トランジションなどを完全に壊してしまうという事実を除いては。したがって、Sync external storeに大きく依存するライブラリを使用している場合、頑張ってください。」
猫が去っています。すぐに戻ります。
言っていたように、Sync external storeはサスペンスや他の楽しい新しい並行機能を壊してしまいます。ですので、それを持つライブラリを使用している場合、他のものが壊れてしまいます。これはTanner Lindsleyのような人々がReactの現状に対して持つ最大の不満の一つであり、彼らは最終的に問題空間を再検討して、useAPIで並行外部ストアを完全にサポートするためのプリミティブを作成しています。useStoreを呼び出し、Reactの並行性、サスペンス、そして本当にアクセスしたいと思っている他のすべてのクールな機能にフレンドリーな方法でストアを実装できます。
これはここで最も短く最もシンプルなセクションかもしれませんが、最も重要なものの一つであり、Reactの周りで構築している多くのコア開発者たちに、間もなく次世代の開発ツールを作るために必要な部品が揃うことを示しています。React Queryのようなものは、これらすべてが最終的に出荷されると、はるかに良くなるでしょう。
Reactに来る全てのクールなことにとても興奮しています。これらのLabsポストが本当に恋しかったです。それらが戻ってきたのは信じられないほど素晴らしいことです。これが来ることを少し早めに知らせてくれたRickyに感謝します。そのおかげで適切に準備ができました。少し早めと言っても、文字通り昨日、たった1日ですが、とても良かったです。
日々、Reactチームはコミュニティとの溝を埋めようとしていると感じます。コミュニティが信じられないほどの規模に成長しているにもかかわらずです。そして私はいつものように、Reactの未来は非常に明るいと考えています。皆さんはどう思いますか?次回まで、平和を、ナード達。
コメント