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

URL永続化

recoil-sync パッケージに組み込まれている外部ストア同期メカニズムの1つは、URL永続化です。これにより、ユーザーはURLに基づいてアトムを簡単に初期化し、アトムが変化したときにURLを更新し、URLの変更(戻るボタンなど)を購読できます。アトムの状態の変更は、現在のURLを置き換えるか、ブラウザの履歴スタックに新しいエントリをプッシュするように設定できます。

アトムをURLと同期させる必要があることを指定する簡単な例を次に示します。

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

次に、アプリケーションのルートに <RecoilURLSyncJSON> を含めるだけで、タグ付けされたすべてのアトムがURLと同期されます。

function MyApp() {
return (
<RecoilRoot>
<RecoilURLSyncJSON location={{part: 'queryParams'}}>
...
</RecoilURLSyncJSON>
</RecoilRoot>
)
}
https://test.com/myapp?CurrentUser=123

URLエンコーディング

状態のシリアライズ

URLで状態をエンコードするために使用できる組み込みメカニズムは2つあります。

  • JSON - <RecoilURLSyncJSON> を使用します。JSONエンコーディング はシンプルで読みやすいです。ただし、カスタムユーザー`クラス`や`Map()`、`Set()`などのコンテナはサポートしていません。Refineの jsonDate() チェッカーを使用すると、`Date`オブジェクトで動作します。
  • Transit - <RecoilURLSyncTransit> を使用します。 Transitエンコーディング は少し冗長ですが、`Map()`および`Set()`コンテナをサポートし、カスタムハンドラーを提供することで独自のクラスをエンコードするように拡張できます。

ベースの <RecoilURLSync> 実装を使用し、独自の `serialize()` および `deserialize()` 実装を提供することもできます。

URLの一部

状態を同期させるURLの部分を設定できます。 location プロパティで、アンカータグに格納する場合は`{part: 'hash'}`、個別のクエリパラメータとして格納する場合は`{part: 'queryParams'}`、単一のクエリパラメータにエンコードする場合は`{part: 'queryParams', param: 'myParam'}` などを指定できます。ライブラリは共存を試み、URLから他のクエリパラメータを削除しません。

プッシュと置換

デフォルトでは、アトムの変更はブラウザの現在のURLを更新された状態に置き換えます。 `syncEffect()` の代わりに `urlSyncEffect()` effect を使用して、この状態の変更によってブラウザの履歴スタックに新しいURLをプッシュする必要があるかどうかなどの追加オプションを指定することもできます。これにより、ブラウザの戻るボタンを使用してこれらの状態の変更を元に戻すことができます。

const currentViewState = atom<string>({
key: 'CurrentView',
default: 'index',
effects: [urlSyncEffect({ refine: number(), history: 'push' })],
});

複数のエンコーディング

異なるストアを持つ異なるアトムを混在させて一致させることができることに注意してください。そのため、一部のアトムを独自のクエリパラメータとしてエンコードして読み取りと解析を容易にし、残りの状態をTransitを使用してユーザークラスをエンコードする単一のクエリパラメータに配置できます。

class ViewState {
active: boolean;
pos: [number, number];
constructor(active, pos) {
this.active = active;
this.pos = pos;
}
...
};
const viewStateChecker = custom(x => x instanceof ViewState ? x : null);

function MyApp() {
return (
<RecoilRoot>
<RecoilURLSyncJSON storeKey="json-url" location={{part: 'queryParams'}}>
<RecoilURLSyncTransit
storeKey="transit-url"
location={{part: 'queryParam', param: 'state'}}
handlers={[
{
tag: 'VS',
class: ViewState,
write: x => [x.active, x.pos],
read: ([active, pos]) => new ViewState(active, pos),
},
]}
/>
...
</RecoilURLSyncTransit>
</RecoilURLSyncJSON>
</RecoilRoot>
)
}

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

const ViewState = atom<ViewState>({
key: 'ViewState',
default: new ViewState(),
effects: [syncEffect({ storeKey: 'transit-url', refine: viewStateChecker() })],
});