11

I am trying to integrate redux-persist with wix react-native-navigation. However, I am unable to find any examples or documentation stating the boilerplate code needed to integrate the both libraries.

I was wondering if anyone would like to share their solution if they have solved this issue ?

Kamil Kamili
  • 1,687
  • 3
  • 17
  • 37

4 Answers4

16

First of all, the basic setup should be the similar with or without react-native-navigation as described in the documentation 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 }
}

The persistStore call is commented out as we'll do it below. The persistStore method takes a callback in its third argument. The callback is executed after the state is restored/rehydrated. This is nice because this means we can delay starting the screen(s) until the state is rehydrated.

Let's assume you have the following bootstrap code in App.js:

store = configureStore()

registerScreens(store, Provider)

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

Now we can add persistStore and wrap your bootstrap code in it like this:

store = configureStore()

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

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

Note: In v4, you pass config instead of null: persistStore(store, config, callback)

Leo Lei
  • 1,514
  • 16
  • 13
2

In case you're looking to integrate it with react-native-navigation v2, in App.js, make sure you call persistStore() inside the registerAppLaunchedListener() :

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

Adding to his solution you can also use subscribe() to check if your user is still logged in. That way they don't need to sign in again if they completely close the app (for those users with a login system) and since it is only called once the store is persisted, you can start your app after this is checked.

    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")
})
Stephen Tapia
  • 106
  • 2
  • 4
0

We actually dont need redux-persist. We can make our own redux-persist with:

redux + store.subscribe(handlechange)

handleChange function will run when ever something changes in our store.

Also Using aync-await(promise) we are not blocking the main execution thread.

So Inside create store add something like:

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

Then inside App.js(first component to load). use AsyncStorage.getItem('store'). Then update the store before app starts.

localstorage on the web is a synchronous function which blocks the main thread.

AsynsStorage in react-native doesn't blocks the main thread.

Rajender Dandyal
  • 291
  • 1
  • 3
  • 10