本日、Recoil 0.0.11をリリースします。バグ修正、新機能、パフォーマンスの向上、そしてコンカレントモードとの実験的な互換性が含まれています。このリリースに貢献してくれたすべての人に感謝します!
実験的なコンカレントモードのサポート
Recoilは、Reactのexperimental
リリースで使用する場合、コンカレントモードをサポートするようになりました。ぜひお試しいただき、問題があればご報告ください!
よりスムーズで一貫性のあるユーザーエクスペリエンスを実現するコンカレントモードは、Reactの未来です。しかし、これまで、あらゆる種類の外部状態との互換性がありませんでした。これは、コンカレントモードでは、レンダリングが時間をかけて分散される可能性があるためです。Reactはコンポーネントのレンダリングを一時停止し、後で中断したところから、すでに構築済みの部分的なコンポーネントツリーから再開できます。

これは、外部状態に関する問題を引き起こします。Reactは制御フローを放棄するため、レンダリングの開始から完了までの間に anything が発生する可能性があります。この間に外部状態が変化すると、先にレンダリングされたコンポーネントは古い状態を観測し、後でレンダリングされたコンポーネントは新しい状態を観測するため、UIに不整合が生じます。

この不整合は、アプリのクラッシュなどの問題を引き起こす可能性があります。
RecoilはReactの実験的なAPIを活用して、レンダリング中にRecoilの状態が変化した場合に新しいツリーで再起動することで、この状況に対処します。これらのAPIは、Recoilの効率を高め、コンポーネントが最初にマウントされたときに再レンダリングする必要性をなくします。
本番環境ではReactの実験的なリリースを使用しないでください。また、Reactや状態管理ライブラリのリリースに関係なく、レンダリング中ではなく、常にuseEffect()
フックに副作用を保持することでバグを回避してください!(@davidmccabe、@bvaughn)
パフォーマンス
いくつかの変更により、Recoilのパフォーマンスが向上しました。以前は、依存関係が不明なセレクターからの読み取り時や、外部ストレージから初期化されたアトムからの読み取り時など、特定の状況でRecoilがコンポーネントを再レンダリングする必要がありました。現在、Recoilはアトムまたはセレクターの読み取りに応じて2回目のレンダリングを実行する必要がなくなりました。(@davidmccabe)
次に、Reactのexperimental
リリースで使用する場合、Recoilはコンポーネントが最初にマウントされたときに2回目のレンダリングを実行する必要がなくなりました。また、Recoilは、アトムまたはセレクターの変更以外の理由で再レンダリングする場合、アトムまたはセレクターの値を検索するための作業を行う必要がなくなりました。(@davidmccabe、@bvaughn)。
useRecoilValue()
やuseRecoilState()
などの基本的なフックが最適化され、現在は約8×高速化されました。現在、通常はuseState()
の実行時間の2×未満です。これにより、多くのコンポーネントで多数のアトムを使用するアプリのパフォーマンスが向上します。(@davidmccabe)
Recoilは、アトムとセレクターの内容を再帰的にフリーズします。これはバグを防ぎますが、大きなオブジェクトでは遅くなる可能性があります。現在は開発ビルドでのみ発生します。(#361— @drarmstr)
Recoilは、すでに設定されている値にアトムを設定した場合、またはすでにリセットされているときにリセットした場合、コンポーネントの再レンダリングまたはセレクターの再評価を回避するようになりました(#399、#386— @drarmstr).
最後に、このリリースでは、以前のリリースで導入されたメモリリークも修正されました。アトムを頻繁に更新するアプリでパフォーマンスが低下している場合は、これが原因である可能性があります。(#471— @davidmccabe)
型とパッケージ
Flow型は、TypeScriptに加えて、パッケージでエクスポートされるようになりました。FlowはFacebookで使用されている型システムであり、Recoilは実際にFlowで記述されています。(#338、#468、#541— @Brianzchen、@Komalov、@mondaychen)
TypeScriptタイピングも改善されました(#492、#545、#548、#568、#575— @csantos42、@SergeyVolynkin、@drarmstr、@hachibeeDI)。
NPMパッケージに加えて、CDN経由でCommon JSおよびUMDモジュールを提供するようになりました(#413— @mondaychen、@pocket7878)。
複数のReactルートのサポート
複数のReactルート間で状態を共有できるようになりました。たとえば、アプリでReact DOMとThreeJSなどの別のレンダラーの両方を使用している場合、Recoilの状態をそれらの間で共有できるようになりました。複数のReactルートを使用する場合、常に、それらは一時的に同期されていない可能性があります。(#298、#516— @drarmstr、@inlet)
開発者ツールAPI
このリリースには、開発者ツール向けの実験的なAPIが含まれています。社内で開発ツールを作成しており、複数のオープンソースプロジェクトも進行中です。これらのAPIをリリースして、その設計の検証に役立てています。(@drarmstr)
その他の新しいAPI
Promiseをアトムのデフォルト値として使用できるようになりました。読み取ると、非同期セレクターのように動作します。(@drarmstr)
バグ修正
このアップデートには、テストインフラストラクチャと、オープンソース環境とFacebook社内環境の違いに関連する多くの修正が含まれています。(#368、#360、#362、#363、#392、#431、#402、#538、#539、#549、#561、#576— @aaronabramov、@Komalov、@drarmstr、@jacques-blom、@mondaychen、@dsainati1、@csantos42、@behnammodi、@habond、@benhalverson)。
また、複数の<RecoilRoot>
を使用する場合、またはスナップショットでセレクターをプリロードする場合のバグも修正されます(#534— @davemccabe).
破壊的変更
このアップデートは、Reactコンポーネントに影響を与えるアクションを実行するためにreact-test-utils
のact()
関数を使用していない特定のテストを壊す可能性があります。これらのテストは、Recoilの追加レンダリングにより、これまでたまたま動作していました。このようなテストを修正するには、act()
を使用してください。
Recoilは、Recoilに提供された状態更新関数が、自身の実行内で別のアトムの更新を引き起こした場合、例外をスローするようになりました。状態更新関数は純粋であることが想定されているため、これは常にAPIの契約に違反していました。しかし、以前はたまたま動作する場合がありましたが、現在は動作しません。このようなコードは、useRecoilCallback()
を使用してエフェクトを実行するように変更できます。
今後の予定
今後のリリースでは、Recoilは、使用されなくなったアトムとセレクターによって使用されているメモリを自動的に解放し、より多数のアトムでより優れたパフォーマンスを発揮するようになります。(@davidmccabe)
また、URL、ローカルストレージ、サーバーなどの外部データソースとRecoilアトムを同期するためのAPIにも取り組んでいます。(@drarmstr)
開発者ツールは開発中です。(@maxijb、@habond、@drarmstr)
ここまで読んでいただき、Recoilをご利用いただきありがとうございます!さらなるリリースが間もなく登場します。