Redux-persist: Redux store

Created on 21 Aug 2017  路  10Comments  路  Source: rt2zz/redux-persist

So I'm trying to implement v5 on a react-native project, I've never used any version of this library before.
This is what I have right now and the issue I'm having is my mapStateToProps state is returning:
{ registry: ['root'], bootstrapped: false }
I think this might be related to https://github.com/rt2zz/redux-persist/issues/408, let me know what you guys think

[email protected]

store.js
```import { createStore, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk'
import { persistStore } from 'redux-persist'

import { check } from 'src/utils'
import reducers from 'src/reducers'

const reduxDevTools = window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()

const applyReduxDevTools = check.isDevAndDebugging && reduxDevTools

const store = createStore(
reducers,
applyReduxDevTools
? compose(applyMiddleware(thunk), applyReduxDevTools)
: compose(applyMiddleware(thunk))
)

export default persistStore(store)

`reducers.js`

import { combineReducers } from 'redux'
import { persistReducer } from 'redux-persist'
import { AsyncStorage } from 'react-native'

import x from 'src/reducers/x'
import y from 'src/reducers/y'

const config = {
version: '0.0.1',
key: 'root',
storage: AsyncStorage,
debug: true
}

const rootReducer = combineReducers({ x, y })

export default persistReducer(config, rootReducer)
```

Most helpful comment

:/ my bad, there was a bug beta.1, just released @5.0.0-beta.2 which I have confirmed resolves the not persisting bug.

All 10 comments

right so the issue is in store.js. the fix:

import thunk from 'redux-thunk'
import { persistStore } from 'redux-persist'

import { check } from 'src/utils'
import reducers from 'src/reducers'

const reduxDevTools = window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()

const applyReduxDevTools = check.isDevAndDebugging && reduxDevTools

const store = createStore(
  reducers,
  applyReduxDevTools
    ? compose(applyMiddleware(thunk), applyReduxDevTools)
    : compose(applyMiddleware(thunk))
)

const persistor = persistStore(store)
export default { store, persistor }

i.e. persistStore returns a persistor not the original store. I recommend you export both so you can pass store to Provider and pass persistor to PersistGate (a component to delay rendering until the rehydration is complete).

LMK If you have suggestions for how to improve the docs to avoid this confusion in the future.

Awesome, I think that worked, I'm getting some import errors now, but I'm pretty sure it's unrelated to redux-persist.
Just more information about persistor vs store would be great, also a complete demo example, so people can follow the setup flow.

Thanks @rt2zz

Didn't want to open a new issue, so I did what you said, and I also looked in the docs more:

// store.js - (Btw you should add the async keyword in the docs)
export default async function configureStore () {
  const initState = await getStoredState(reducerConfig)

  const store = createStore(
    reducers,
    initState,
    check.isDevAndDebugging
      ? compose(applyMiddleware(thunk), check.isDevAndDebugging)
      : applyMiddleware(thunk)
  )

  listeners(store)

  const persistor = persistStore(store)

  return { store, persistor }
}

then in my entry point:

import configureStore from 'src/store'

const { store, persistor } = configureStore()

console.log(configureStore(), 'configureStore')
// One of those have the store and persistor objects I'm looking for
// Promise {_40: 0, _65: 0, _55: null, _72: null}

console.log(store, 'store')
// undefined

const App = () => (
  <Provider store={store}>
    <PersistGate
      persistor={persistor}
      loading={<Loading />}
      onBeforeLift={() => console.log('lifted')}
    >
      <Container>
        <StatusBar hidden />

        <ScreenRoot />
      </Container>
    </PersistGate>
  </Provider>
)

export default App

Am I supposed to handle this promise with a class component and react cycles? I feel that it would be a hacky fix, thoughts on this @rt2zz ?

no need to use getStoredState. I would update configureStore as follows:

export default function configureStore () {
  const store = createStore(
    reducers,
    undefined,
    check.isDevAndDebugging
      ? compose(applyMiddleware(thunk), check.isDevAndDebugging)
      : applyMiddleware(thunk)
  )

  // @NOTE not sure what this does, assuming listeners is defined outside of this method?
  listeners(store)

  const persistor = persistStore(store)

  return { store, persistor }
}

also note: the reason you had a promise was that async functions always return promises. Make sure you remove the async flag on configureStore

Got it, I thought I had to add that initial state, also to clarify I do need to update my redux store manually if a local version has been found right? I had to dispatch this in order for the PersistGate component to show the root component instead of the loading one:

persistor.dispatch({ type: REHYDRATE })

Problem I'm having now is all my other actions are not working as before, maybe something to do with the async initial state I was doing? need to try it tomorrow.

no you should not need to manually do persistor.dispatch({ type: REHYDRATE }) that happens under the hood. I think maybe you still need to wrap your reducer in persistReducer, e.g.

import { persistStore, persistReducer } from 'redux-persist'
//...

export default function configureStore () {
  const persistedReducer = persistReducer(reducers)
  const store = createStore(
    persistedReducer,
    undefined,
    check.isDevAndDebugging
      ? compose(applyMiddleware(thunk), check.isDevAndDebugging)
      : applyMiddleware(thunk)
  )

  // @NOTE not sure what this does, assuming listeners is defined outside of this method?
  listeners(store)

  const persistor = persistStore(store)

  return { store, persistor }
}

I'm already doing that:

// src/reducers.js
export const reducerConfig = {
  version: VERSION,
  key: 'root',
  storage: AsyncStorage,
  debug: check.isDevAndDebugging
}

const rootReducer = combineReducers({
  a,
  b
})

export default persistReducer(reducerConfig, rootReducer)

:/ my bad, there was a bug beta.1, just released @5.0.0-beta.2 which I have confirmed resolves the not persisting bug.

Awesome, it works now, thank you so much @rt2zz :) Great work

Was this page helpful?
0 / 5 - 0 ratings