Open michaelolof opened 5 years ago
I think it's a good idea to simplify the API, and make it usable without any processing. However I'm not quite sold on the way of declaring mutations, as I don't think it should enforce a specific way of naming the method and field names. My suggestion is that mutations should be defined as setters, ie.
class Person extends initializeStore({ namespaced: true }) {
// [...]
// mutation
set Bio(bio :Bio ) {
this.firstname = bio.firstname;
this.lastname = bio.lastname;
this.age = bio.age
}
// [...]
}
Another options is to drop mutations all together, as (I'm pretty sure) Vuex will in the future merge actions and mutations.
Hello @asmadsen thanks for all your work thus far.
Setters was the original idea. but the problem with setters is that their types are not predictable.
From that example, assuming a proxy was created.
const person = createProxy( Person );
console.log( person.bio ) // undefined
The user will naturally expect person.bio
to return a value since bio
is a property with type {firstname :string, lastname :string, age :number}
but he gets undefined
since the property has no corresponding getter. And there is no way of telling from the type system.
Getters on their own are safe because the type system will immediately mark any getter defined without a setter as readonly
.
PS: The library will actually prevent you from using setters
without getters
and tell you to either define a corresponding getter
or define it explicitly with a function assignment.
Also on this:
as I don't think it should enforce a specific way of naming the method and field names
The library actually doesn't enforce a particular naming convention for mutations. We could have called it mutateBio
or doSomethingCrazy
and it would still work as long as you're doing a function assignment instead of a function declaration
Another options is to drop mutations all together, as (I'm pretty sure) Vuex will in the future merge actions and mutations.
On this I quite agree, but I don't think they have come up with how that will work. We also can't be ahead of them. What if they decide to change course.
Also I feel with the implicit mutations you get from your proxies, you'd hardly have to reach for the mutation functions unless you want to do mass mutations of your state.
I would agree with you when it comes to not making features that deviate from core Vuex functionality. However I think that it's better to add magic inside the actions so they act as mutations as well. Rather than relying of the difference being function assignment vs function declaration since it's not really clear why they do different things.
So in my opinion it's better to wait for Vuex to merge the concepts of actions and mutations or turn the setters on this passed to actions into small mutations.
Rather than relying of the difference being function assignment vs function declaration since it's not really clear why they do different thing
I understand your concern on this. I generally don't feel this is a deal breaker though.
So in my opinion it's better to wait for Vuex to merge the concepts of actions and mutations or turn the setters on this passed to actions into small mutations.
This I totally agree with. I wish Vuex will just give us a simple function that has access to the context object. We can then decide if that function will return void
a promise
or even a simple value. basically just like any normal function would.
I will have to disagree with you there, because as far as I know there is rarely expected to any JS developer that function declaration and function assignment is supposed to result in different functionality (other than the classic
this
binding).
And I would argue that also will be a deviation from the original Vuex interface, since it's not clear from just reading the code that the difference between the function declaration and the function assignment is a functional choice and not a style choice.
In that case I would say that it's clearer to understand that any function could manipulate the state, and there is no separation of actions and mutations.
So an update on this.
I'm still very much interesting in fading out decorators from the API. Thus while th @mutation
@action
@Module
@getter
decorators will still be supported.
I won't be adding any additional decorators to the API.
The updated API proposal would look like this.
import { initializeModule, mutation } from "vuex-class-component";
const VuexModule = initializeModule({
namespaced: true,
enableLocalWatcher: true,
enableLocalSubscriber: true,
enableLocalSubscriberAction: true,
})
class Person extends VuexModule {
// state
firstname = "Michael";
lastname = "Olofinjana";
age = 20;
// explicit mutation
@mutation setBio( bio :Bio ) {
this.firstname = bio.firstname;
this.lastname = bio.lastname;
this.age = bio.age
}
// actions
@action async fetchBio() { ... }
@action async tryAnotherAsync { ... }
// getters
get fullname() {
return this.firstname + " " + this.lastname;
}
// mutation for getter (only allowed for getters)
set fullname( fullname ) {
const names = fullname.split( " " );
this.firstname = names[ 0 ];
this.lastname = names[ 1 ];
}
// watch getters and states
static $watch = {
firstname() {
console.log( "firstname has changed." );
}
fullname( this :Person, newVal :string, oldVal :string ) {
this.age = 22;
console.log( "new:", newVal, "old:", oldVal );
}
}
// subscribe to mutations.
static $subscribe = {
setBio( this :Person, payload :Bio ) {
console.log( "Set bio mutation has been called", payload );
}
}
// subscribe to actions.
static $subscribeAction = {
fetchBio( this :Person, payload :any ) { ... }
tryAnotherAsync: {
before: ( this :Person, payload :any ) { ... },
after: ( this :Person, payload :any ) { ... }
}
}
}
This looks great! When will the new API be available to use?
What happened to this? Looked good.
A lot of the motivation behind this new proposal is making the Class API feel and work as much as natural classes as possible.
New Class Declaration API - (No Decorators)
Cleaner Extraction of Vuex Modules and Proxies
Automatic Getters an Mutations for your States = 10x More Powerful Proxies.
What do you think?