web-dev-qa-db-ja.com

React Native Navigation and Redux Persist

私はredux-persistをwix react-native-navigationと統合しようとしています。ただし、両方のライブラリを統合するために必要な定型コードを示す例やドキュメントを見つけることができません。

この問題を解決した場合、ソリューションを共有したい人がいるかどうか疑問に思っていましたか?

10
Kamil Kamili

まず、基本的なセットアップは、react-native-navigationの有無にかかわらず、 ドキュメントで in _store.js_のようになります。

_import { persistStore, persistCombineReducers } from 'redux-persist'
import storage from 'redux-persist/es/storage' // default: 
localStorage if web, AsyncStorage if react-native
import reducers from './reducers' // where reducers is an object of 
reducers

const config = {
  key: 'root',
  storage,
}

const reducer = persistCombineReducers(config, reducers)

function configureStore () {
  // ...
  let store = createStore(reducer)
  return store

  // We'll skip persistStore for now
  // let persistor = persistStore(store)
  //return { persistor, store }
}
_

persistStore呼び出しは、以下で行うためコメント化されています。 persistStoreメソッドは、3番目の引数でコールバックを受け取ります。コールバックは、状態が復元/復元された後に実行されます。これは、状態が再水和されるまで画面の開始を遅らせることができることを意味するためです。

App.jsに次のbootstrap=コードがあると仮定します。

_store = configureStore()

registerScreens(store, Provider)

Navigation.startTabBasedApp({
  tabs: [{...},]
})
_

これで、persistStoreを追加して、bootstrapコードを次のようにラップできます。

_store = configureStore()

persistStore(store, null, () => {
  registerScreens(store, Provider)

  Navigation.startTabBasedApp({
    tabs: [{...},]
  })
})
_

注:v4では、nullの代わりにconfigを渡します:persistStore(store, config, callback)

16
Leo Lei

App.jsでreact-native-navigation v2と統合する場合は、必ずpersistStore()内でregisterAppLaunchedListener()を呼び出してください:

import { persistStore } from 'redux-persist';
...
Navigation.events().registerAppLaunchedListener(() => {
  persistStore(store, null, () => {
    Navigation.registerComponentWithRedux(...);
    ...
    Navigation.setRoot({...})
     ...
  })
})
2
Jojo

彼のソリューションに加えて、subscribe()を使用して、ユーザーがまだログインしているかどうかを確認することもできます。そうすれば、アプリを完全に閉じた場合(ログインシステムを持つユーザーの場合)、は、ストアが永続化された後にのみ呼び出されます。これをチェックした後、アプリを起動できます。

    import {Platform, AsyncStorage, AppState} from "react-native"
    import {Navigation} from "react-native-navigation"
    import {registerScreens} from "./routes"
    import {Provider} from "react-redux"
    import configureStore from "./stores/reduxStore"
    import {Component} from "react"

      const storage = configureStore()

      registerScreens(Provider, storage.store)

let startapp = screen => {
  Navigation.startSingleScreenApp({
    screen: {
      screen, // unique ID registered with Navigation.registerScreen
      navigatorStyle: {
        navBarHidden: true,
        statusBarHidden: false,
        statusBarColor: "white",
        statusBarTextColorScheme: "dark"
      }, // override the navigator style for the screen, see "Styling the navigator" below (optional)
      navigatorButtons: {} // override the nav buttons for the screen, see "Adding buttons to the navigator" below (optional)
    },
    drawer: {
      left: {
        screen: "Drawer", // unique ID registered with Navigation.registerScreen
        passProps: {} // simple serializable object that will pass as props to all top screens (optional)
      }
    },
    tabsStyle: {
      // optional, add this if you want to style the tab bar beyond the defaults
      tabBarButtonColor: "#ffff00", // optional, change the color of the tab icons and text (also unselected). On Android, add this to appStyle
      tabBarSelectedButtonColor: "#ff9900", // optional, change the color of the selected tab icon and text (only selected). On Android, add this to appStyle
      tabBarBackgroundColor: "#551A8B", // optional, change the background color of the tab bar
      initialTabIndex: 1 // optional, the default selected bottom tab. Default: 0. On Android, add this to appStyle
    },
    appStyle: {
      orientation: "portrait"
    }
  })
}

storage.persistor.subscribe(() => {
  storage.store.getState().user.logged
    ? startapp("mainscreen")
    : startapp("loginscreen")
})
0
Stephen Tapia

実際にはredux-persistは必要ありません。次のようにして独自のredux-persistを作成できます。

_redux + store.subscribe(handlechange)
_

handleChange関数は、ストアで何かが変更されたときに実行されます。

また、aync-await(promise)を使用して、メイン実行スレッドをブロックしていません。

そのため、ストアの作成中に次のようなものを追加します。

_store.subscribe(async ()=>{
 try {
 await AsyncStorage.setItem("store", JSON.stringify(store.getState()));
 } catch (error) {
  // Error 
 } 
})
_

次に、App.js内(最初にロードするコンポーネント)。 AsyncStorage.getItem('store')を使用します。次に、アプリを起動する前にストアを更新します。

Web上のlocalstorageは、メインスレッドをブロックする同期関数です。

react-nativeのAsynsStorageは、メインスレッドをブロックしません。

0