web-dev-qa-db-fra.com

Comment et où enregistrer l'intégralité du magasin Redux à l'aide d'AsyncStorage

Je me demandais si je devais faire quelque chose comme ça pour enregistrer tout le magasin de mon application en utilisant AsyncStorage dans mon application native et réagir si elle existe au démarrage de l'application.

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>
    )
  }
}

Cela ne fonctionne pas mais j'espère que vous avez compris.

12
Luis Rizo

Utilisez redux-persist pour ne pas avoir à utiliser directement AsyncStorage.

13
wmcbain

Oui, c'est l'une des façons dont votre application peut récupérer son état à partir de AsyncStorage. Cependant, la façon dont vous souhaitez gérer les données dépend de l'application et des données elles-mêmes.

Personnellement, j'ai tendance à ne pas enregistrer l'ensemble de l'App Store. Certaines sections de votre application peuvent avoir besoin d'être récupérées lors de la navigation entre les scènes, il n'est pas logique de les conserver dans AsyncStorage. Il en va de même pour la scène actuelle et les données similaires, qui doivent être conservées dans le magasin redux, mais seront probablement réinitialisées au redémarrage de l'application.

En ce qui concerne l'enregistrement des données dans AS, la façon que je recommanderais est middleware redux . Vous interceptez les actions dont vous avez besoin et effectuez AsyncStorage.setItem(). Je suppose que c'est ok de le faire ailleurs, comme dans le code des composants. Ce n'est pas si propre, mais c'est à votre goût, vraiment. Remarque concernant les clés - Je stocke simplement différents jeux de données dans différentes clés AsyncStorage. De cette façon, vous gérez moins de données à chaque mise à jour du magasin (pas tout l'arborescence d'état, mais seulement sa section). Le code du middleware ressemblera à ce qui suit:

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
}

Notez que vous n'avez pas besoin de faire await ici car dans la plupart des cas, il est correct d'écrire des données de manière asynchrone (sauf si vous allez les lire et les utiliser tout de suite, ce qui ne devrait pas être le cas si vous utilisez magasin redux)

Concernant le démarrage de l'application - vous pouvez utiliser AsyncStorage.multiGet pour obtenir toutes les clés immédiatement et les mettre en magasin. Suite aux 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
    })
  })
})

Une fois que vous avez lu le AsyncStorage et récupéré les données, il est logique de les combiner en un objet d'état préchargé qui sera similaire à votre App Store et de définir le magasin Redux via une seule action. Vous pouvez l'appeler APP_STATE_INIT, passez-lui l'objet nouvellement combiné et capturez l'action dans vos réducteurs qui ont besoin d'utiliser les données. De cette façon, vous n'aurez qu'une seule action pour réhydrater votre état au démarrage de l'application.

Vous aurez probablement besoin d'un état de chargement qui affectera l'affichage du chargeur jusqu'à ce que les valeurs AS soient récupérées et que les données soient remplies dans le magasin redux. Mais dans l'ensemble, vous avez raison, vous pouvez mettre le AsyncStorage init et le temps d'attente à componentWillMount

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

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

Si vous pensez que pour votre application, vous pouvez tout enregistrer et démarrer en fonction de cela, n'hésitez pas à utiliser l'un des packages qui permettent de réhydrater l'app store du stockage de manière simple. Je voudrais simplement noter l'effet potentiel sur les performances et le fait que vous perdez ainsi le contrôle de ce qui se passe.

18
dhorelik