web-dev-qa-db-ja.com

AsyncStorageを使用してreduxストア全体を保存する方法と場所

反応ネイティブアプリでAsyncStorageを使用してアプリのストア全体を保存し、アプリの起動時に存在するかどうかを確認するために、このようなことをする必要があるかどうか疑問に思っていました。

var store;

_loadInitialState = async () => {
  try {
    var value = await AsyncStorage.getItem(STORAGE_KEY);
    if (value !== null){
      store = value;
      console.log('Recovered selection from disk: ' + value);
    } else {
      store = configureStore({});
      console.log('Initialized with no selection on disk.');
    }
  } catch (error) {
    console.log('AsyncStorage error: ' + error.message);
  }
};



export default class App extends Component {

  componentWillMount(){
    this._loadInitialState().done()
  }

  render(){
    return(
      <Provider store={store}>
        <AppContainer/>
      </Provider>
    )
  }
}

これは機能しませんが、アイデアが得られることを願っています。

12
Luis Rizo

redux-persist を使用して、AsyncStorageを直接使用する必要がないようにします。

13
wmcbain

はい、これはアプリがAsyncStorageから状態を取得できる方法の1つです。ただし、データの処理方法はアプリとデータ自体に依存します。

個人的には、アプリストア全体を保存しない傾向があります。シーン間を移動するときにアプリの一部のセクションを再取得する必要がある場合がありますが、AsyncStorageに保持することは意味がありません。同じことが現在のシーンと同様のデータについて行われます。これはreduxストアに保存されますが、おそらくアプリの再起動時にリセットされます。

データをASに保存することに関して、私が推奨する方法は reduxミドルウェア です。必要なアクションをインターセプトし、AsyncStorage.setItem()を実行します。コンポーネントのコードのように、他の場所でそれをしても大丈夫だと思います。それはそれほどきれいではありませんが、本当にあなたの好み次第です。キーに関する注意-異なるAsyncStorageキーに異なるデータセットを保存するだけです。この方法では、ストアの更新ごとに処理するデータが少なくなります(状態ツリー全体ではなく、セクションのみです)。ミドルウェアのコードは次のようになります。

export default store => next => (action) => {
  let result = next(action)

  switch (action.type) {
    case THE_ACTION_THAT_REQUIRES_AN_ASYNCSTORAGE_UPDATE:
      AsyncStorage.setItem('@your_key', action.data_that_is_to_be_stored)
      break

    case ANOTHER_ACTION:
      // similar here
      break

    default:
      break
  }

  return result
}

ここでawaitを実行する必要はないことに注意してください。ほとんどの場合、非同期でデータを書き込むことができます(すぐにデータを読み取って使用する場合を除きます。 redux store)

アプリの起動に関して-AsyncStorage.multiGetすべてのキーをすぐに取得して保管します。 RN docs の後に:

AsyncStorage.getAllKeys((err, keys) => {
  AsyncStorage.multiGet(keys, (err, stores) => {
   stores.map((result, i, store) => {
     let key = store[i][0]
     let value = store[i][1]

     // add your data to redux store
    })
  })
})

AsyncStorageを読み取ってデータを取得したら、それをアプリストアに似たプリロードされた状態オブジェクトに結合し、1回のアクションでReduxストアを設定するのが理にかなっています。 APP_STATE_INIT、新しく結合されたオブジェクトをそれに渡し、データを使用する必要があるレデューサーでアクションをキャッチします。この方法では、アプリの起動時に状態を回復するためのアクションが1つだけあります。

AS値が取得され、データがreduxストアに入力されるまで、表示されるローダーに影響するロード状態がおそらく必要になります。しかし、全体的には正しいです。AsyncStorage initを入れてcomponentWillMountに待機することができます

...
async componentWillMount() {
  await _loadInitialState()

  this.setState({
    isLoading: false
  })
}
...

アプリのすべてを保存し、それに基づいて起動してもよいと考えている場合は、ストレージからアプリストアを再水和する簡単な方法を提供するパッケージのいずれかを使用してください。パフォーマンスへの潜在的な影響と、この方法で何が起こっているかを制御できなくなるという事実に注意してください。

18
dhorelik