メインコンテンツへスキップ

·1分間の読書
  • useRecoilCallback()における潜在的な未処理のPromise拒否を修正 (#2075)
  • RecoilEnv.RECOIL_GKS_ENABLEDを介したGateKeeper機能の切り替えに対するOSSサポートを追加 (#2078)
  • SSRで使用される非同期セレクターのサスペンスの解決を修正 (#2073, #1960)
  • Next.JS 13で使用されるReact DOMの一部のバージョンでのSSRを修正 (#2082, #2086)

·1分間の読書
  • "重複したatomキー"のチェック/ログを無効にするフラグを公開。NextJSやFast Refreshを使用する一部の開発環境ではノイズが多すぎたため。(#733, #2020, #2046)

    • recoilパッケージからRecoilEnvをインポートし、コード内でRecoilEnv.RECOIL_DUPLICATE_ATOM_KEY_CHECKING_ENABLED = falseを設定してチェックとログを無効にします。
    • NextJsなどのNodeJS環境ではprocess.env.RECOIL_DUPLICATE_ATOM_KEY_CHECKING_ENABLED=falseもサポートしています。
    • 注意: これにより、正当なエラーを含む重複したatomキーのすべてのチェックが無効になりますので、注意して使用してください!
  • useSyncExternalStore()をサポートしていないネストされたレンダラーを持つReact 18環境の回避策。(#2001, #2010)

·1分間の読書
  • listenプロップコールバックで<RecoilSync>updateItem()updateAllKnownItems()に加えてupdateItems()をエクスポートしました。(#2017, #2035)
  • URLからパラメータを削除すると、paramを持つlocation queryParamsを使用する場合、atomがリセットされます。これは、atomが複数のURLパラメータと同期する場合に、わずかな破壊的変更になります。(#1900, #1976)
  • <RecoilURLSyncTransit>で不安定なhandlersプロップが検出された場合に、開発警告を追加しました。(#2044)

·1分間の読書
  • boolean()エクスポートをbool()に名前変更 (booleanは予約語のため) (#1922, #1962, #1971)
  • react-nativeのエラーをクリーンアップするために、package.jsonnativeディレクトリへの参照を削除しました。(#1931)
  • カスタムチェッカー用のPathクラスをエクスポートしました。(#1950, #1956)
  • union()or()のエラーメッセージを各タイプで拡張しました。(#1961)

·1分間の読書
  • 開発中のReactのFast Refreshを使用したuseRecoilSnapshot()を修正しました (#1891)
  • Chrome v104以降で変更されたブラウザの動作に伴うuseRecoilSnapshot()recoil-syncを修正しました (#1943, #1936)

·3分間の読書

recoil-syncNPMパッケージの最初のオープンソースリリース!Recoil Syncは、Recoilの状態を外部システムと同期するのに役立つアドオンライブラリを提供します。シンプルな非同期データクエリは、セレクターまたはuseEffect()を介して実装できます。または、個々のatomの双方向同期にはatomエフェクトを使用できます。recoil-syncアドオンパッケージは、いくつかの追加機能を提供します。

  • バッチ処理されたアトミックトランザクション - 複数のatomの更新を、外部システムとの単一のトランザクションとしてまとめてバッチ処理できます。これは、関連するatomの一貫した状態に必要なアトミックトランザクションの場合に重要です。
  • 抽象的で柔軟性が高い - このAPIを使用すると、同期方法を説明することとは別に、同期するatomを指定できます。これにより、コンポーネントは、実装を変更することなく、異なる環境で異なるシステムとatomを使用し、同期できます。たとえば、コンポーネントは、スタンドアロンツールで使用する場合にURLに永続化するatomを使用し、別のツールに埋め込まれた場合はカスタムユーザーデータベースに永続化する場合があります。
  • 検証と下位互換性 - 外部ソースからの状態を扱う場合、入力を検証することが重要です。状態がアプリの寿命を超えて永続化される場合、以前のバージョンの状態との下位互換性を考慮することも重要です。recoil-syncrefineは、この機能を提供するのに役立ちます。
  • atomと外部ストレージの複雑なマッピング - atomと外部ストレージアイテムの間に一対一のマッピングがない場合があります。atomはアイテムの新しいバージョンを使用するように移行したり、複数のアイテムからプロップを取得したり、複合状態の一部だけを使用したり、その他の複雑なマッピングを行う場合があります。
  • Reactフックまたはプロップとの同期 - このライブラリを使用すると、atomエフェクトからアクセスできないReactフックまたはプロップとatomを同期できます。

recoil-syncライブラリは、ブラウザのURLとの同期など、外部ストアの組み込み実装も提供します。


基本的な考え方は、同期する各atomにsyncEffect()を追加し、次に<RecoilRoot>内に<RecoilSync>を追加して、これらのatomを同期する方法を指定することです。<RecoilURLSyncJSON>などの組み込みストアを使用したり、独自に作成したり、異なるストアを使用して異なるatomのグループを同期したりすることもできます。

URL永続化

ブラウザのURLとatomを同期する簡単な例を以下に示します。atomをブラウザのURLと同期する

const currentUserState = atom<number>({
key: 'CurrentUser',
default: 0,
effects: [
syncEffect({ refine: number() }),
],
});

次に、アプリケーションのルートで、<RecoilURLSyncJSON>を含めて、これらのタグ付きatomをすべてURLと同期します。

function MyApp() {
return (
<RecoilRoot>
<RecoilURLSyncJSON location={{part: 'queryParams'}}>
...
</RecoilURLSyncJSON>
</RecoilRoot>
)
}

以上です!これで、このatomは初期ロード時にURLに基づいて状態を初期化し、状態の変更によってURLが更新され、URLの変更(戻るボタンなど)によってatomが更新されます。同期効果ストアの実装URL永続化のガイドで、詳細な例を参照してください。

·2分間の読書

FlowとTypeScriptの型リファインメントと入力検証のための@recoiljs/refineライブラリの最初のオープンソースリリース!Refineについて学習を開始するには、ユーティリティチェッカーのコアコンセプトに関するドキュメントをご覧ください。

Recoil Syncライブラリは、型リファインメント、入力検証、下位互換性のためのタイプのアップグレードにRefineを活用しています。recoil-syncドキュメントで詳細をご覧ください。

Refineを使うメリットは?

  • コードでTypeScriptのunknown型またはFlowのmixed型の値が検出され、それらの値が特定の静的型であることをアサートする必要がある場合、Refineは便利です。
  • Refineは、未知の値が期待される型に準拠していることを検証できる型リファインメントヘルパー関数を構築するためのAPIを提供します。
  • Refineは入力値を検証し、以前のバージョンからアップグレードできます。

型リファインメントの例

未知の型を厳密に型付けされた変数に変換します。assertion()は、入力が期待される型と一致しない場合に例外をスローし、coercion()nullを返します。

const myObjectChecker = object({
numberProperty: number(),
stringProperty: optional(string()),
arrayProperty: array(number()),
});

const myObjectAssertion = assertion(myObjectChecker);
const myObject: CheckerReturnType<myObjectChecker> = myObjectAssertion({
numberProperty: 123,
stringProperty: 'hello',
arrayProperty: [1, 2, 3],
});

下位互換性のある例

match()asType()を使用すると、以前の型から最新バージョンにアップグレードできます。

const myChecker: Checker<{str: string}> = match(
object({str: string()}),
asType(string(), str => ({str: str})),
asType(number(), num => ({str: String(num)})),
);

const obj1: {str: string} = coercion(myChecker({str: 'hello'}));
const obj2: {str: string} = coercion(myChecker('hello'));
const obj3: {str: string} = coercion(myChecker(123));

JSONパーサーの例

RefineはJSONをラップして、組み込みの厳密に型付けされたパーサーを提供します。

const myParser = jsonParser(
array(object({num: number()}))
);

const result = myParser('[{"num": 1}, {"num": 2}]');

if (result != null) {
// we can now access values in num typesafe way
assert(result[0].num === 1);
} else {
// value failed to match parser spec
}

·1分間の読書
  • 欠落していたFlow型を修正しました(#1857
  • セレクターのデフォルト値を持つアトムを使用する場合のメモリリークをクリーンアップしました。(#1821#1840#1844

·1分間の読書

GraphQLを使用するためのrecoil-relayライブラリの最初のオープンソースリリースです!

このライブラリは、GraphQLRelayライブラリを使用して、Recoilが型安全で効率的なクエリを実行するのに役立ちます。GraphQLで簡単にクエリを実行できるセレクターを提供します。クエリはRecoilデータフローグラフと同期されるため、下流のセレクターはそこから状態を導き出し、上流のRecoil状態に依存し、Relayからのグラフの変更を自動的に購読します。すべてが自動的に同期された状態を保ちます。

GraphQLクエリは、GraphQLセレクターを定義するほど簡単です。

const userNameQuery = graphQLSelector({
key: 'UserName',
environment: myEnvironment,
query: graphql`
query UserQuery($id: ID!) {
user(id: $id) {
name
}
}
`,
variables: ({get}) => ({id: get(currentIDAtom)}),
mapResponse: data => data.user?.name,
});

次に、他のRecoilセレクターと同様に使用します。

function MyComponent() {
const userName = useRecoilValue(userNameQuery);
return <span>{userName}</span>;
}

·1分間の読書
  • ファミリーパラメータでアトムとセレクターを使用できるようにしました(#1740
  • アトムインスタンスが複製された親RecoilストアであるparentStoreID_UNSTABLEをアトムエフェクトに追加しました。これにより、GraphQLのプリフェッチパターンが可能になります。(#1744
  • アトムエフェクトは、アトムをラップされた値に初期化または設定できます(#1681