rt2zz / redux-persist

persist and rehydrate a redux store
MIT License
12.91k stars 863 forks source link

localForage not working inside getStoredState Function #132

Closed muratgozel closed 7 years ago

muratgozel commented 8 years ago

I'm using persistStore and getStoredState functions at different locations in my app.

persistStore comes after redux's createStore function (as usual):

/* @flow */
import { createStore, applyMiddleware, compose } from 'redux'
import thunkMiddleware from 'redux-thunk'
import { persistStore, autoRehydrate } from 'redux-persist'
import rootReducer from '../reducers'
import reduxPersistOptions from './options'
import DevTools from '../dev/ReduxDevTools'

export default (initialState: Object) => {

  let enhancer = compose(
    applyMiddleware(thunkMiddleware),
    autoRehydrate(),
    DevTools.instrument()
  )

  const store = createStore(rootReducer, initialState, enhancer)

  persistStore(store, reduxPersistOptions)

  // enable hot reload
  if (module.hot) {
    module.hot.accept('../reducers', () => {
      const nextRootReducer = require('../reducers').default;
      store.replaceReducer(nextRootReducer);
    });
  }

  return store
}

And getStoredState called by the root component of my app. (Inside componentDidMount) :

function verifyCredentials(props, callback) {
  getStoredState(reduxPersistOptions, (err, restoredState) => {
    let token = Object.keys(restoredState).length === 0 ? '' : restoredState.client.token
    let cid = Object.keys(restoredState).length === 0 ? '' : restoredState.client.cid

    fetch('/api/user/credentials', {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        token: token || '',
        cid: cid || ''
      })
    }).then(function(resp) {
      return resp.json()
    }).then(function(json) {
      props.onSaveToken( json.token || '' )
      props.onSaveCID( json.cid || '' )
      callback(null, props, json.token, json.cid )
      return
    }).catch(function(err) {
      callback(err)
      return
    })
  })
}

My redux persist configuration has only 2 args which are whitelist and storage :

/* @flow */
import localForage from 'localForage'

const devOptions = {
  whitelist: ['client'],
  storage: localForage
}

const prodOptions = {
  whitelist: ['client'],
  storage: localForage
}

module.exports = process.env.NODE_ENV === 'production' ? prodOptions : devOptions

When i build the app, i receive an error that says getStoredState.js:43 Error in storage.getAllKeys

If i remove the localForage from the options, everything works fine. Removing getStoredState function from my root component is also fine.

getStoredState.js:43

...
  storage.getAllKeys(function (err, allKeys) {
    if (err && process.env.NODE_ENV !== 'production') {
      console.warn('Error in storage.getAllKeys');
    }
    var persistKeys = allKeys.filter(function (key) {
...
rt2zz commented 8 years ago

Hm, can you log out the actual error i.e. replace the console.warn with console.warn('Error in storage.getAllKeys', err);

muratgozel commented 8 years ago

Yes. localforage.js:694 Uncaught (in promise) TypeError: Cannot read property 'name' of null(…)

localforage.js:694:

...
// Specialize the default `ready()` function by making it dependent
// on the current database operations. Thus, the driver will be actually
// ready when it's been initialized (default) *and* there are no pending
// operations on the database (initiated by some other instances).
function _fullyReady(callback) {
    var self = this;

    var promise = self._initReady().then(function () {
/* LINE 694 */ var dbContext = dbContexts[self._dbInfo.name];

        if (dbContext && dbContext.dbReady) {
            return dbContext.dbReady;
        }
    });

    promise.then(callback, callback);
    return promise;
}
...

It says _dbInfo has no name property. So i also log the self object: Image

It looks like _dbInfo is null.

omichelsen commented 7 years ago

Did you figure this one out? I have the same problem, but only in Safari. It breaks my whole app though.

rt2zz commented 7 years ago

@omichelsen @muratgozel sounds like an upstream localForage issue? localForage is great, but if needed you can always switch back to the asyncLocalStorage provided by redux-persist

muratgozel commented 7 years ago

I have restructured my module by removing getStoredState function. The problem was occur in all browsers for me.