What is the best approach in dynamic Vuex module initialisation when using Nuxt.js?
Asked Answered
D

2

9

Lately, I have been building a large scale application that uses a lot of separate Vuex modules. Let's take a look at one of them (e.g. support-chat). Support chat is located on it's own separate page, and it would be redundant to pollute the store with this module on initial application load. My goal is to register this module dynamically when it's page is loaded. So my question is – where, when and how should I register that module?

I end up registering this module in the beforeCreate hook of the page component:

import supportChatModule from '@/vuex/modules/support-chat'

// ...
beforeCreate() {
  this.$store.registerModule('support-chat', supportChatModule, { preserveState: process.client })
},
beforeDestroy() {
  this.$store.unregisterModule('support-chat')
}
// ...

What pitfalls does that approach have?

It would be great if you can share your approach in solving that issue.

Decasyllabic answered 13/11, 2019 at 21:10 Comment(1)
why exactly does the default not work for you? can you elaborate?Tribune
H
4

I struggled with this problem for a long time. I finally came up with a unique way. I did this by moving register and unregister the modules for each page into the router file (router/index.js in my project) in beforeEach method and adding the required modules for each path.

  • Some modules are shared between pages, which solves this problem.
  • Some modules receive large amounts of data from the server, which is better than staying on the client side to avoid receiving this data again. I did this with a freezer.

This method can be improved.

router/index.js

router.beforeEach((to, from, next) => {

  // unregister modules
  if (from.meta.modules) {
    for (const key in from.meta.modules.primary) {
      if (to.meta.modules && to.meta.modules.primary.hasOwnProperty(key)) {
        continue;
      }
      if (store.state.hasOwnProperty(key)) {
        // don't unregister freeze modules
        if (from.meta.modules.hasOwnProperty('freeze') && from.meta.modules.freeze.find(item => item == key)) {
          continue;
        }
        store.unregisterModule(key);
      }
    }
  }
  // register modules
  if (to.meta.modules) {
    for (const key in to.meta.modules.primary) {
      const module = to.meta.modules.primary[key]();
      if (!store.state.hasOwnProperty(key)) {
        store.registerModule(key, module.default);
      }
    }
  }
});

And my paths are like this:

{
  path: 'users',
  name: 'users',
  meta: {
    modules: {
      primary: {
        user: () => require('@/store/modules/moduleUser')
      }
    },
  },
  component: () => import('../views/users.vue')
},

{
  path: 'foods',
  name: 'foods',
  meta: {
    modules: {
      primary: {
        food: () => require('@/store/modules/moduleFood'),
        user: () => require('@/store/modules/moduleUser')
      },
      freeze: ['food']
    },
  },
  component: () => import('../views/foods.vue')
},
Hexad answered 14/9, 2020 at 16:33 Comment(1)
Looks great, looking forward to check it outDecasyllabic
S
1

Step 1:

Create a mixin, I named it register-vuex-module.js:

export const registerVuexModule = (name, module) => ({
  beforeCreate() {
    const { $store } = this

    if ($store.hasModule(name)) $store.commit(`${name}/resetState`)
    else $store.registerModule(name, module().default)
  }
})

Step 2: Use the mixin to import a module:

<template>
...
</template>

<script>
// Mixins
import { registerVuexModule } from '@/mixins/register-vuex-module'

export default {
  mixins: [registerVuexModule('module-name', () => require('./vuex/MyVuexModule.js'))],
}
</script>

Step 3:

Make sure your Vuex module has a resetState mutation and also the state gets returned from a function. Here is an example of how MyVuexModule.js should look like:

const initialState = () => ({
  count: null
})

export default {
 namespaced: true,

 state: initialState(),

 mutations: {
  // ...
  resetState: state => Object.assign(state, initialState())
 }
}
Stocktonontees answered 7/6, 2021 at 10:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.