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

Suggestion to Vuex best practice when using nested modules #1459

Open
JaeYeopHan opened this Issue Nov 27, 2018 · 0 comments

Comments

Projects
None yet
1 participant
@JaeYeopHan

JaeYeopHan commented Nov 27, 2018

What problem does this feature solve?

IMHO, there are several problems with Vuex.

  1. Overuse string when using mapState, mapGetters, mapActions
  2. Duplicated namespace in components

like this:
my-component.vue (AS-IS version)

export default {
  computed: {
    ...mapState("todos", {
      allItems: ({ items }) => items,
    }),
    ...mapGetters("todos", {
      doneItems: "doneItems",
      activeItems: "activeItems",
    }),
  }
}

In this code, "doneItmes" is written by string. It will cause bug easily.
And there are duplicated namespace called "todos". It will inhibit maintainabillity.

What does the proposed API look like?

The way to introduce it is not to suggest a new API, but to use the existing API properly.
We can use createNamespacedHelpers API with constants in store directory!

Example

@/store/todos/types.js

export const NAMESPACE = "todos";

@/store/todos/index.js

import { createNamespacedHelpers } from"vuex";
import { NAMESPACE } from "./types";

// Key point !
const { mapState, mapGetters, mapActions } = createNamespacedHelpers(NAMESPACE);

export { mapState, mapGetters, mapActions };

export default { /* namespaced, state, getters, mutations, actions */ }

@/store/todos/getters.js

// Key point !
export const DONE_ITEMS = "DONE_ITEMS";
export const ACTIVE_ITEMS = "ACTIVE_ITEMS";

export default {
  [DONE_ITEMS]: state => state.items.filter(todo => todo.isDone),
  [ACTIVE_ITEMS]: state => state.items.filter(todo => !todo.isDone)
};

If we do this, we can use customized binding helpers.

my-component.vue (TO-BE version)

import * as todos from '@/store/todos'; // Key point !
import * as getters from '@/store/todos/getters'; // Key point !
import * as actions from '@/store/todos/types'; // Key point !

export default {
  computed: {
    ...todos.mapState({
      allItems: ({ items }) => items,
    }),
    ...todos.mapGetters([
      getters.DONE_ITEMS,
      getters.ACTIVE_ITEMS,
    ])
  },
  methods: {
    ...todos.mapActions([
      actions.ADD_ITEM,
    ]),
  }
}

How about this? If you do not mind this, I would like to post it on the official Vuex document.
You can see the all example code in this repository

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment