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

code demo for section 'Store Code Splitting' not valid #240

Open
dyf19118 opened this issue Apr 18, 2019 · 1 comment
Open

code demo for section 'Store Code Splitting' not valid #240

dyf19118 opened this issue Apr 18, 2019 · 1 comment

Comments

@dyf19118
Copy link

Please refer to this section 'Store Code Splitting'.

{
  // here follows critical code in given demo
  computed: {
    fooCount () {
      return this.$store.state.foo.count;
    },
  },
  serverPrefetch () {
    this.registerFoo()
    return this.fooInc()
  },
  mounted () {
    this.registerFoo()
  },
  destroyed () {
    this.$store.unregisterModule('foo')
  },
  methods: {
    registerFoo () {
      this.$store.registerModule('foo', fooStoreModule, { preserveState: true })
    },
  },
}

Given that we have a route componet Fruit with path '/fruits/:id'. At the first time we visit the page '/fruits/1', during server-side rendering, store module 'foo' will be registered and the final global state will be injected into HTML as window.__INITIAL__STATE, once client app start hydrating, client app's state will be replaced by window.__INITIAL__STATE, after entering the route /fruits/:id, module 'foo' will be registered as expected and keeps previous state not changed. So far, that's all ok (except this problem #239 i'v found before). But once you leave this route, destroyed hook will be called and module 'foo' will be unregistered. Then we click history back button, we'll back to this route and since module 'foo' has not been registered yet, computed property fooCount will cause an TypeError because this.$store.state.foo is undefined.
Oops...That's not the biggest problem! The worst thing is that after mounted hook called and this.registerFoo() called, the 'foo' module will still be registered with option { preserveState: true } and as a result this.$store.state.foo will always be undefined (previous state has no property 'foo' due to unregistration).
That's the problem.

Here follows my solution: no duplicated module registration and no unregistration, then everything will be ok.

{
    computed: {
      fooCount () {
        return this.$store.state.foo.count;
      },
    },
    methods: {
      registerFoo(preserve = false) {
        if (!this.$store._modules.root._children['foo']) {
          this.$store.registerModule('foo', storeModuleFoo, { preserveState: preserve });
        }
      },
    },
    serverPrefetch() {
      this.registerFoo();

      return this.fooInc();
    },
    mounted() {
      this.registerFoo(true);
    },
  }

I'm not sure is this solution valid, please give your advice if anything went wrong, thanks all.

@garretmh
Copy link

garretmh commented Jul 3, 2019

A minimal solution is to set preserveState to true whenever the module state already exists.

{
  // here follows critical code in given demo
  computed: {
    fooCount () {
      return this.$store.state.foo.count;
    },
  },
  serverPrefetch () {
    this.registerFoo()
    return this.fooInc()
  },
  mounted () {
    this.registerFoo()
  },
  destroyed () {
    this.$store.unregisterModule('foo')
  },
  methods: {
    registerFoo () {
      this.$store.registerModule('foo', fooStoreModule, {
        // Preserve state if it exists.
        preserveState: this.$store.state.foo
      })
    },
  },
}

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

2 participants