vuex-class-modules
vuex-class-modules copied to clipboard
wrapped Action (accessing context)
Is it possible to define an Action that gets wrapped in another function?
Example of wrapping an action using vuexfire:
actions: {
bindTodos: firestoreAction(({ bindFirestoreRef }) => {
// return the promise returned by `bindFirestoreRef`
return bindFirestoreRef('todos', db.collection('todos'))
}),
}
I've tried a few different ways.
@Action
bindTodos1 = firestoreAction(({ bindFirestoreRef }) => {
// return the promise returned by `bindFirestoreRef`
return bindFirestoreRef('todos', db.collection('todos'))
})
// ^ Unable to resolve signature of property decorator when called as an expression. ts(1240)
@Action
bindTodos2 () {
return firestoreAction(({ bindFirestoreRef }) => {
return bindFirestoreRef('todos', db.collection('todos'))
})
}
// ^ compiles, and seems to execute, but does not update 'todos' state property
bindTodos3 = firestoreAction(({ bindFirestoreRef }) => {
return bindFirestoreRef('todos', db.collection('todos'))
})
@Action
bindTodos4 () {
return this.bindTodos3()
}
Is there a specific syntax or even a workaround to get a firestoreAction into a VuexModule ?
You could define your own decorator for it:
function FirestoreAction(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.value = firestoreAction(descriptor.value);
return descriptor;
}
Then use it as:
@Action
@FirestoreAction
bindTodos({ bindFirestoreRef }) {
return bindFirestoreRef('todos', db.collection('todos'));
}
At least I think that should work. Haven’t tried it myself.
Thanks @bodograumann that helps.
bindFirestoreRef is something that is injected into the context by firestoreAction, so its not a parameter to mymodule.bindTodos()
In regular actions, the first param is the context:
actions: {
bindTodos({ commit, state }) {
// ...
}
}
How can that context be accessed inside either the FirestoreAction decorator or in the bindTodos action?
Here is a FirestoreAction decorator that uses firestoreAction to create the action, and then calls it (from here)
export function FirestoreAction() {
return function(_target: any, _key: string, descriptor: PropertyDescriptor) {
const delegate: Function = descriptor.value
descriptor.value = function(payload: any) {
const action = firestoreAction((context) => {
const thisObj = { context }
return delegate.call(thisObj, payload)
}) as Function
// @ts-ignore
return action(this.context)
}
}
}
But this.context is undefined.
Here is an action without the decorator which might work if the context was available (this.context) in the action.
@Action
bindTodos () {
return (firestoreAction(({ bindFirestoreRef }) => {
return bindFirestoreRef('bindTodos', firestore.collection('bindTodos'))
}) as Function)(this.context)
}
Is there anyway to get the context?
The context in vanilla vuex corresponds to this when using vuex-class-modules.
It is a proxy which allows you to access the properties which are valid in the current context. So for actions you can directly access state, mutations and other actions.
I don’t think you can simply use this instead of context for firestoreAction though, because vuexfire relies heavily on vanilla vuex api.
Not sure how to combine vuexfire and vuex-class-modules. vuex-class-modules’ purpose is to hide the internal vuex api and only expose a class interface, while vuexfire is in its essence using all the technical details of the vanilla vuex api.