ngrx-store-localstorage icon indicating copy to clipboard operation
ngrx-store-localstorage copied to clipboard

Primitive values are unserialized to strings

Open yannickglt opened this issue 6 years ago • 3 comments

My state looks like:

{
  "name": "John",
  "age": 12,
  "married": false,
  "children": []
}

And I use the metareducer as below:

localStorageSync({
  keys: ['name', 'age', 'married'],
  rehydrate: true
})(reducer)

It causes issues because it will create three different entries in the localStorage with the respective values "John", "12" and "false". During unserialization, these entries will remain strings as they are not parsed using JSON.parse (because they are not object-like values) and will equal "12" (I mean "12" as a string).

A possible alternative is to avoid storing primitive values, but it is quiet hard to keep in mind and does not look to be a bad practice (as I could not find any article about this topic). Another solution would be to always store states as objects instead of values. Another benefit would be to avoid multiplication of entries in the localStorage (one entry per state instead of one per key). The result in the localStorage would look like:

{"name":"John","age":12,"married":false}

Such a change would have incident on the way serialization is done and the main consequences would be:

  • the given keys property would only filter on the properties we want to keep during serialization
  • a name should be given to the LocalStorageConfig, corresponding to the feature name or the root.

I can create a PR if this suggestion looks viable to you and is wanted for the future.

yannickglt avatar Mar 26 '18 13:03 yannickglt

Any update regarding this issue?

firehist avatar Apr 04 '18 16:04 firehist

You could pass a reviver function that parses the non-string keys. Assuming that the state slice is called person, it should be something like this:

const personReviver = (key, value) => {
    switch (key) {
        case 'age':
            return Number(value);
        case 'married':
            return !!!value;
        default:
            return value;
    }
};

localStorageSync({ keys: [{ person: { reviver: personReviver } }], rehydrate: true })(reducer);

ernestomancebo avatar Aug 17 '18 15:08 ernestomancebo

You can try the following:

localStorageSync({
  keys: ['name', { age: { deserialize: parseInt } }, 'married'],
  rehydrate: true
})(reducer)

steffbeckers avatar Nov 08 '23 12:11 steffbeckers