championswimmer / vuex-persist

A Vuex plugin to persist the store. (Fully Typescript enabled)
http://championswimmer.in/vuex-persist
MIT License
1.67k stars 117 forks source link

Deepmerge breaks modules not related to persist #216

Open Magiczne opened 3 years ago

Magiczne commented 3 years ago

After updating to vuex-persist 3.1.3 modules that are not related in any way to vuex-persist plugin are broken when they're using classes as a part of state. Also i'm using vuex-module-decorators.

For example:

class Foo {
  a = 5;
  bar () {
    this.a = 6;
  }
}

@Module({ namespaced: true, name: 'foo' })
class FooModule extends VuexModule {
  foo = new Foo();

  @Mutation
  baz () {
    this.foo.bar();
  }
}

const persist = new VuexPersist({ 
  modules: ['other', 'some-other-module-2']
})

On the application start it throw an error that foo.bar() is not a function. It would make sense when the module would be loaded by vuex-persist but it it not so it should be not touched.

Everything worked fine when the backend besides merging was handled by lodash. Everything broke after moving to deepmerge.

What it the solution to this? Temporarily we're using older version but that's not a good option for a long time.

championswimmer commented 3 years ago

Can you make a sample github repo with a small contrivied example that faces this issue. I would really love to checkout on my machine and actually debug this properly.

Magiczne commented 3 years ago

@championswimmer - https://github.com/Magiczne/vuex-persist-bug-poc

Click the button and it will fail spectacularly: image

Comment line 40 in the src/store/index.ts and it's working completely fine.

chaitanyapotti commented 3 years ago

I'm facing this issue too.! Another place is in reducer.. it uses deepmerge and the class instance is dead and it's custom stringifying logic is no longer present

Can we have an option to do this without deepmerge?

Magiczne commented 3 years ago

I have ended up writing this functionality on my own in the projects I'm using it with, caues it looks that library is somehow abandoned.

I also couldn't find any reason besides #64 why lodash was replaced when it was working perfectly fine.

chaitanyapotti commented 3 years ago

image

As present in the image, i had to do three things to overcome this.

  1. in restoreState, create my class again
  2. Fix the reducer
  3. Write a new plugin which doesn't do deepmerge
nokazn commented 3 years ago

I have a similar issue. I created store including Map and Set value in state, but both are converted to empty objects.

import Vuex from 'vuex';
import VuexPersistence from 'vuex-persist';

const store = new Vuex.Store({
    state: {
        // Expected empty Map, but actually object
        map: new Map(),
        set: new Set(),
    },
});
const persist = new VuexPersistence({
    storage: window.localStorage,
    reducer: (state) => ({ map: state.map }),
}).plugin(store);

This is caused by the behavior of merging object by deepmerge, which replaced lodash.merge from 3.x.

I think another library like just-extend or something should be used. just-extend is a zero-dependency package, so its bundle size is tiny.