Recoil公式ドキュメント 翻訳⑩ ガイド-Stateの永続性

Recoilの公式ドキュメントをgoogle翻訳するとコードまで翻訳されてしまうのが面倒なのでQiitaにまとめてみます。

追々追加していきます。

[公式ドキュメント](https://recoiljs.org/docs/basic-tutorial/selectors)

## 目次

* **前書き**　[①](https://qiita.com/Daichi44/items/4236857dac4a3365f434)　[②](https://qiita.com/Daichi44/items/f6f8995a73387d104777)　[③](https://qiita.com/Daichi44/items/b46d9659c8fcfad2c227)　[④](https://qiita.com/Daichi44/items/3356aaeb7a387b520621)
* **基本チュートリアル**　[⑤](https://qiita.com/Daichi44/items/ee1ced6040d06e33e165)　[⑥](https://qiita.com/Daichi44/items/d6c2472043b473c9819d)　[⑦](https://qiita.com/Daichi44/items/af3d6363ac3ce3e7af5a)
* **ガイド**
 * [⑧非同期データクエリ](https://qiita.com/Daichi44/items/47e9ac34c61c35531abb)
 * [⑨非同期state・同期state](https://qiita.com/Daichi44/items/ae631b34ac50fb9bbd1d)
 * <font color="orange">**⑩Stateの永続性**</font>
* **APIリファレンス**
 * **Core**　[⑪](https://qiita.com/Daichi44/items/b440f33d3831b86c62b9)　[⑫](https://qiita.com/Daichi44/items/0a9b9af69dddddbcd7e2)　[⑬](https://qiita.com/Daichi44/items/13912706763c22f9cbe9)　[⑭](https://qiita.com/Daichi44/items/812aa5ebf149c849e108)　[⑮](https://qiita.com/Daichi44/items/2ec591ec3e952f1784c3)　[⑯](https://qiita.com/Daichi44/items/f78a2ce0cfc01de354c5)　[⑰](https://qiita.com/Daichi44/items/ab0e98e0a48d0a59bdb4)　[⑱](https://qiita.com/Daichi44/items/a887cfa33260136b1d68)　[⑲](https://qiita.com/Daichi44/items/679030df40e81a608be5)　[⑳](https://qiita.com/Daichi44/items/f682baf85f0e2673abfc)　[㉑](https://qiita.com/Daichi44/items/1c38716dc0738da3bc02)　[㉒](https://qiita.com/Daichi44/items/84a7218e76f62d41d0b7)　[㉓](https://qiita.com/Daichi44/items/de7e39f80cd1fdce8b7c)　[㉔](https://qiita.com/Daichi44/items/eda197468b0204349d5f)　[㉕](https://qiita.com/Daichi44/items/0bbe5d6643462b55df11)　[㉖](https://qiita.com/Daichi44/items/0a276eb144f443a72efd)　[㉗](https://qiita.com/Daichi44/items/78292a5c30b1b1e4813f)
 * **実用(utils)**　[㉘](https://qiita.com/Daichi44/items/c6046e45ba7447a64aed)　[㉙](https://qiita.com/Daichi44/items/f552dfda4765596d83d7)　[㉚](https://qiita.com/Daichi44/items/7e568ccfb6d2e504de13)　[㉛](https://qiita.com/Daichi44/items/6973c6d140b697b2c97e)　[㉜](https://qiita.com/Daichi44/items/b929ff5376d0672dafa0)　[㉝](https://qiita.com/Daichi44/items/e9720f6ceb7cea57b2ce)　[㉞](https://qiita.com/Daichi44/items/c9bb722022a003d72aa9)　[㉟](https://qiita.com/Daichi44/items/ca11fcef04d764ef13a8)

※[全目次](https://qiita.com/Daichi44/items/45093185eb06fb4e1171#%E5%85%A8%E7%9B%AE%E6%AC%A1)は一番下にあります

***

# Stateの永続性

Recoilを使用すると、atomを使用してアプリケーションのstateを保持できます。


***

### *重要なお知らせ*
*このAPIは現在開発中であり、今後変更される予定です。お楽しみに...*

***


## Stateの保存
stateを保存するには、atomの変更を登録し、新しいstateを記録します。
React effectsを使用して、個々のatomを登録できます。(*[非同期state・同期state](https://qiita.com/Daichi44/items/ae631b34ac50fb9bbd1d)*参照)
ただし、Recoilはhookを提供し、[`useRecoilTransactionObserver_UNSTABLE()`](https://recoiljs.org/docs/api-reference/core/useRecoilTransactionObserver)を使用してすべてのatomのstate変更を登録できるようにします。

サブスクリプションコールバックは、すべてのatom stateを提供し、変更されたatomを通知します。
ここから、好みのストレージと[シリアライゼーション](http://dic-it.fideli.com/dictionary/m/word/w/11678/index.html)で変更を保存できます。
以下は、JSONを使った基本的な実装の例です。

```React
function PersistenceObserver() {
  useRecoilTransactionObserver_UNSTABLE(({snapshot}) => {
    for (const modifiedAtom of snapshot.getNodes_UNSTABLE({isModified: true})) {
      const atomLoadable = snapshot.getLoadable(modifiedAtom);
      if (atomLoadable.state === 'hasValue') {
        Storage.setItem(
          modifiedAtom.key,
          JSON.stringify({value: atomLoadable.contents}),
        );
      }
    }
  });
}
```

記憶域は、ブラウザのURL履歴、*[LocalStorage](https://developer.mozilla.org/ja/docs/Web/API/Window/localStorage)、[AsyncStorage](https://github.com/react-native-community/react-native-async-storage)*、または任意の記憶域です。

すべてのatomを持続させたくないかもしれませんし、いくつかのatomは異なる持続性を持っているかもしれません。
*atomごとのstate同期APIがまもなく登場するので、検討してみてください。*

## Stateの復元
stateをストレージに保存したら、アプリケーションをロードするときに復元する必要があります。これは、[`<RecoilRoot>`](https://recoiljs.org/docs/api-reference/core/RecoilRoot)コンポーネントの`initializeState`プロパティを使用して実行できます。

`initializeState`は、[MutableSnapshot](https://recoiljs.org/docs/api-reference/core/Snapshot#transforming-snapshots)に初期atom値を設定する`set()`メソッドを提供する関数です。この値は初期レンダリングに使用されます。`useEffect()`hookでatom値を手動で設定すると、最初にデフォルト値を使用した初期レンダリングが行われ、無効になったり[フリッカー](https://www.sophia-it.com/content/flicker)が発生したりする可能性があります。

次に基本的な例を示します。

```React
const initializeState = ({set}) => {
  for(const [key, value] of Storage.entries()) {
    set(myLookupOfAtomWithKey(key), JSON.parse(value).value);
  }
}

return (
  <RecoilRoot initializeState={initializeState}>
    <PersistenceObserver />
    <SomeComponent />
  </RecoilRoot>
);
```

*注：`myLookupOfAtomWithKey()`は、keyに基づいて登録されたatomを検索するための擬似コードです。一部のatomは動的に、またはatom族を介して定義されるので、これは最良のアプローチではありません。atomごとの同期効果を定義する新しいAPIが近く公開される予定なので、より使いやすくなるはずです。*

## 同期中 State
また、ユーザーがURL永続性を使用してブラウザーの戻るボタンを押すなど、ストレージの非同期更新を現在のアプリケーションのstateと同期させることもできます。React effectを使用すると、これらの変更を適用し、変更されたatomの値を直接更新できます。

>サンプルは近日公開予定...

## 下位互換性と値の検証
state記憶装置が信頼できない場合はどうすればよいでしょうか。
あるいは、使用しているatomまたはタイプを変更し、以前に永続化されたstateを操作する必要がある場合はどうすればよいでしょうか。
>APIが完成し次第、これを処理する方法についてのドキュメントと例を追加予定...

***

### 参考サイト
・[公式ドキュメント](https://recoiljs.org/docs/basic-tutorial/selectors)
・[フィデリ・IT用語辞典 シリアライゼーション](http://dic-it.fideli.com/dictionary/m/word/w/11678/index.html)
・[IT用語辞典 BINARY フリッカ](https://www.sophia-it.com/content/flicker)
・[みらい翻訳](https://miraitranslate.com/trial)

***

>## 全目次
* **前書き**
 * [①動機](https://qiita.com/Daichi44/items/4236857dac4a3365f434)
 * [②コアコンセプト](https://qiita.com/Daichi44/items/f6f8995a73387d104777)
 * [③インストール](https://qiita.com/Daichi44/items/b46d9659c8fcfad2c227)
 * [④入門](https://qiita.com/Daichi44/items/3356aaeb7a387b520621)
* **基本チュートリアル**
 * [⑤概要](https://qiita.com/Daichi44/items/ee1ced6040d06e33e165)
 * [⑥Atoms](https://qiita.com/Daichi44/items/d6c2472043b473c9819d)
 * [⑦Selectors](https://qiita.com/Daichi44/items/af3d6363ac3ce3e7af5a)
* **ガイド**
 * [⑧非同期データクエリ](https://qiita.com/Daichi44/items/47e9ac34c61c35531abb)
 * [⑨非同期状態・同期状態](https://qiita.com/Daichi44/items/ae631b34ac50fb9bbd1d)
 * <font color="orange">**⑩Stateの永続性**</font>
* **APIリファレンス**
 * **Core** <br>
   •　[⑪ \<RecoilRoot /\>](https://qiita.com/Daichi44/items/b440f33d3831b86c62b9) <br>
   •　**State** <br>
   　・　[⑫`atom()`](https://qiita.com/Daichi44/items/0a9b9af69dddddbcd7e2) <br>
   　・　[⑬`selector()`](https://qiita.com/Daichi44/items/13912706763c22f9cbe9) <br>
   　・　[⑭Loadable](https://qiita.com/Daichi44/items/812aa5ebf149c849e108) <br>
   　・　[⑮`useRecoilState()`](https://qiita.com/Daichi44/items/2ec591ec3e952f1784c3) <br>
   　・　[⑯`useRecoilValue()`](https://qiita.com/Daichi44/items/f78a2ce0cfc01de354c5) <br>
   　・　[⑰`useSetRecoilState()`](https://qiita.com/Daichi44/items/ab0e98e0a48d0a59bdb4) <br>
   　・　[⑱`useResetRecoilState()`](https://qiita.com/Daichi44/items/a887cfa33260136b1d68) <br>
   　・　[⑲`useRecoilValueLoadable()`](https://qiita.com/Daichi44/items/679030df40e81a608be5) <br>
   　・　[⑳`useRecoilStateLoadable()`](https://qiita.com/Daichi44/items/f682baf85f0e2673abfc) <br>
   　・　[㉑`isRecoilValue()`](https://qiita.com/Daichi44/items/1c38716dc0738da3bc02) <br>
   •　**Snapshots** <br>
   　・　[㉒Snapshot](https://qiita.com/Daichi44/items/84a7218e76f62d41d0b7) <br>
   　・　[㉓`useRecoilTransactionObserver()`](https://qiita.com/Daichi44/items/de7e39f80cd1fdce8b7c) <br>
   　・　[㉔`useRecoilSnapshot()`](https://qiita.com/Daichi44/items/eda197468b0204349d5f) <br>
   　・　[㉕`useGotoRecoilSnapshot()`](https://qiita.com/Daichi44/items/0bbe5d6643462b55df11) <br>
   •　[㉖`useRecoilCallback()`](https://qiita.com/Daichi44/items/0a276eb144f443a72efd) <br>
   •　**雑録(Misc)** <br>
   　・　[㉗`useRecoilBridgeAcrossReactRoots()`](https://qiita.com/Daichi44/items/78292a5c30b1b1e4813f) <br>
 * **実用(utils)** <br>
   •　[㉘`atomFamily()`](https://qiita.com/Daichi44/items/c6046e45ba7447a64aed) <br>
   •　[㉙`selectorFamily()`](https://qiita.com/Daichi44/items/f552dfda4765596d83d7) <br>
   •　[㉚`constSelector()`](https://qiita.com/Daichi44/items/7e568ccfb6d2e504de13) <br>
   •　[㉛`errorSelector()`](https://qiita.com/Daichi44/items/6973c6d140b697b2c97e) <br>
   •　[㉜`waitForAll()`](https://qiita.com/Daichi44/items/b929ff5376d0672dafa0) <br>
   •　[㉝`waitForAny()`](https://qiita.com/Daichi44/items/e9720f6ceb7cea57b2ce) <br>
   •　[㉞`waitForNone()`](https://qiita.com/Daichi44/items/c9bb722022a003d72aa9) <br>
   •　[㉟`noWait()`](https://qiita.com/Daichi44/items/ca11fcef04d764ef13a8) <br>