Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to serialise #4

Open
lid2000 opened this issue Apr 13, 2016 · 2 comments
Open

Unable to serialise #4

lid2000 opened this issue Apr 13, 2016 · 2 comments

Comments

@lid2000
Copy link

lid2000 commented Apr 13, 2016

I'm getting errors using this with redux-persist 2.0 as persistor.rehydrate is being passed an object instead of a string, which causes the deserialise function to die. My workaround has been to parse the newValue value, then stringify the whole statePartial object:

statePartial[keyspace] = JSON.parse(e.newValue); persistor.rehydrate(JSON.stringify(statePartial), function(){ //@TODO handle errors? })

@rt2zz
Copy link
Owner

rt2zz commented Apr 13, 2016

Good catch. It seems the most elegant solution is for redux-persist's persistor.rehydrate to detect if the incoming state is a string and deserialize accordingly.

@oroce
Copy link

oroce commented Apr 20, 2016

A little bit better solution is writing your own serializer and deserializer:

import { createStore, compose } from 'redux';
import { persistStore, autoRehydrate } from 'redux-persist';
import crosstabSync from 'redux-persist-crosstab';
const finalCreateStore = compose(autoRehydrate())(createStore);
const store = finalCreateStore(reducer);

const persistor = persistStore(store, {
  serializer: serializer,
  deserializer: deserializer
});
crosstabSync(persistor);

// this is exactly the same what redux-persist uses
function serializer(data) {
   return JSON.stringify(data);
}
function deserializer(data) {
   // this is the normal deserialization process
   if (typeof data === 'string') {
      return JSON.parse(data);
   }
   // basically we need to deserialize this one:
   // var o = {
   //     f: '{"foo":"bar"}',
   //     b: '{"bar":"foo"}'
   // };

   return Object.keys(data).reduce(function(obj, key) {
     obj[key] = JSON.parse(data[key]);
     return obj;
   }, {});
}

Or we could modify redux-persist-crosstab to support serialization/deserialization:

var constants = require('redux-persist/constants')
var keyPrefix = constants.keyPrefix

module.exports = function(persistor, config){
  var config = config || {}
  var blacklist = config.blacklist || false
  var whitelist = config.whitelist || false
  var serialize = config.serialize || function(data) {
     return JSON.stringify(data)
  }
  var deserialize = config.deserialize || function(data) {
    return JSON.parse(data)
  }
  window.addEventListener('storage', handleStorageEvent, false)

  function handleStorageEvent(e){
    if(e.key.indexOf(keyPrefix) === 0){
      var keyspace = e.key.substr(keyPrefix.length)
      if(whitelist && whitelist.indexOf(keyspace) === -1){ return }
      if(blacklist && blacklist.indexOf(keyspace) !== -1){ return }

      var statePartial = {}
      statePartial[keyspace] = deserialize(e.newValue)
      persistor.rehydrate(serialize(statePartial), function(){
        //@TODO handle errors?
      })
    }
  }
}

First one looks uglier but the latter one can hurt the performance :(

So probably the best would be having support in redux-persist for rehydrating serialized data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants