greenpress/vuex-composition-helpers

Vuex official mappers

krystian50 opened this issue · 6 comments

Question

Hi, in my project we use vuex mappers in a way:

...mapActions('user', ['resetPassword']),

Is it possible to achieve that with your library? Basically I want to be able to use:
mapActions(module: String, actions: [])

Proposal

I made a small wrapper for traditional mappers:

export function useActions(...args) {
  const appContext = { $store: useStore() };
  const mappedActions = mapActions(...args); //vuex mapper
  const mappedActionsContext = mapValues(mappedActions, el => el.bind(appContext));

  return mappedActionsContext;
}

And then usage:
const storeActions = useActions('user', ['resetPassword']);

It's very tested yet, but seems to work fine. The same for getters:

export function useGetters(...args) {
  const appContext = { $store: useStore() };
  const contextMapGetters = mapGetters.bind(appContext);
  const mappedGetters = contextMapGetters(...args);
  const mappedGettersContextValues = mapValues(mappedGetters, el => el.bind(appContext));
  // wrap everything in refs, the only way to keep it reactive
  const refs = mapValues(mappedGettersContextValues, val => computed(val));

  return refs;
}

I already did it.
In fact, I've added a pull request to vuex, so make their "mapXX" work for compositions as-well.
They closed my PR with the reason that "it's not a bug - it's a feature".

BTW, where is your implementation of useStore()? AFAIK, this function doesn't yet officially exist.

I haven't seen vuex mapActions in your implementation. Mostly I would like to know if I can use your library in such way. I mean:
...mapActions('user', ['resetPassword']),

About your question, my store is exposed in JS file so I simply do:

import store from '@/store';

export function useStore() {
  return store;
}

you can use it as I've shown in the bottom of the readme file:
consider to replace your "useStore" with that code:

import { wrapStore } from 'vuex-composition-helpers';
import store from '@/store';

export default wrapStore(store);

now, on your component you can write:

import { createNamespacedHelpers } from './wrapped-store.js';
const { useActions } = createNamespacedHelpers('user');

export default {
 name: 'ResetPassword',
 setup() {
   return {
     ...useActions(['resetPassword'])}
   }
}

Is that ok?

I'm aware of that solution. The thing is, we use in our project mappers in the way I wrote above. We are adding now composition-api. We don't wanna change all mappers to createNamespacedHelpers . That's why I wrote my own wrapper to keep all possibilities gave by official VueX mapper. Anyway, I'm not actually a fan of namespacedHelpers, because at the end you have:

const { useActions: useUserActions } = createNamespacedHelpers('user');
const { useActions: useListActions } = createNamespacedHelpers('list');
...

The capability exists inside my code (the "useMappers" internal function inside global.ts file).
As "yad2.co.il" did - they forked my code to use it.. and you can also fork it instead of using it thought npm directly.
The other option is that you can suggest a PR, and I'll gladly merge it (just keep it elegant and simple, and don't break current behavior) 😄 .

I always love the second option!

@krystian50 Iv'e added the ability (version 1.0.12) to use the global helpers (I'll add the "namespaced" later) without providing the store to the hook manually.
You can see the README update as well.
Also, it's now has better typings and unit tests.