Skip to content

Add an option to disallow direct state modification from component #58

@Aaron-Pool

Description

@Aaron-Pool

In the example, I kind of dislike the fact that the component can directly call cart.state.rawItems = [];. Just because I think that can encourage people to modify state in a disorganized manner. Can we get a plugin setting that disallows state being modified from the component (rather than an explicit action)?

Activity

changed the title [-]Add an option to disallow direct state modification[/-] [+]Add an option to disallow direct state modification from component[/+] on Jan 21, 2020
posva

posva commented on Jan 22, 2020

@posva
Member

I think disallowing direct state modification is a rule that should be enforced at a linter level instead because runtime-wise this would only be a dev-only warning, so it would be slower during dev and require more code in the library

Being able to directly modify the state (or using patch) is intentional to lower the entry barrier and scale down. After many years using Vuex, most mutations were completely unnecessary as they were merely doing a single operation via an assignment (=) or collection methods like push. They were always perceived as verbose, no matter the size of the project, adding to the final bundle size as well, and were useful only when grouping multiple modifications and some logic, usually in larger projects. In Pinia, you are still able to have these groups by using actions but you get to choose if you need them or not, being able to start simple, and scale up when necessary.

So I want to make people realise mutations is an unnecessary concept thanks to actions and that the cost of mutations and its verbosity is not enough to justify the possibility of organisation it brings. On top of that, one of the main aspects of mutations was devtools: being able to go back and forward. In Pinia, all modifications are still tracked so doing direct state modification still allows you to keep things organised despite it wasn't taught that way with Vuex

Aaron-Pool

Aaron-Pool commented on Jan 22, 2020

@Aaron-Pool
Author

@posva just to clarify, I wasn't requesting to disallow direct state mutation in actions. I was only requesting to disallow direct state mutation from component methods. I agree that mutations feel like overkill, and I'm happy to see the concept of mutations is absent from pinia. I do, however, think that only being allowed to modify state through actions encourages a concise, and thought-through API for state management and modification. It also creates an incentive to only put state in vuex that really needs to be there, and use component local state for everything else, rather than the "put everything in vuex" approach that I often see people take, which doesn't seem to scale well.

All that being said, your reasoning about it being a linter-level feature, rather than an implementation feature makes perfect sense 👌

Thanks for the quick response!

posva

posva commented on Jan 22, 2020

@posva
Member

I wasn't requesting to disallow direct state mutation in actions

Yes, of course, disallowing it in actions would make my response nonsense 😆

sisou

sisou commented on Feb 1, 2020

@sisou

Vue 3 includes a readonly() method that makes anything passed into it read-only. This could be used for the exported state, which would show an error with Typescript and log an error/stop mutations during runtime.

Futhermore, Typescript has a Readonly<> type modifier that can be used for Typescript errors already in Vue 2.

Would you consider using either of those?

raphaelkieling

raphaelkieling commented on Jun 24, 2020

@raphaelkieling

And the patch still exist? because if i would need show or hide a card, i will need create a action called showCard(active) it's sounds a vuex mutation. I agree with @posva to only create a dev warning, this is horrible to scale larger pages but in some cases this is a option

koljada

koljada commented on Sep 27, 2020

@koljada

I am also trying to avoid mutating the state outside the store and would love to use actions for that.
How is it possible to show linter warnings when changing the store's state in components?

added a commit that references this issue on May 12, 2021
5745ce8
linked a pull request that will close this issue on May 12, 2021
posva

posva commented on May 12, 2021

@posva
Member

Opened #493 to try to get more feedback

soylomass

soylomass commented on Jul 26, 2021

@soylomass

In a little store experiment I was working on before finding about Pinia, thinking about this problem, I implemented the following solution:

Add an "autoSetters" boolean that would to the configuration:

  • Make the exposed state readonly
  • For each state property, automatically create a setter function (store.name -> store.setName). Used TS template literals to make typescript and code completion work as expected.

So for the following state:

export const useMainStore = defineStore({
  id: 'main',
  autoSetters: true,
  state: () => ({
    counter: 0,
    name: 'Eduardo',
  })
});

You would get:

const main = useMainStore();
// Error
main.counter = 2;
// Ok
main.setCounter(2);
// Error
main.name = 'Fede';
// Ok
main.setName('Fede');

I found this to be natural and worked fine. Is there any issue or caveat you can think of about this kind of solution?

I don't really like the fact of having "magic" methods auto-generate, but it was the best-looking / less verbose of all solutions I could think of.


EDIT: Now that I re-read the original comment, I realized that the point of the issue was to centralize state modification inside explicitly defined actions, so this wouldn't solve that. My goal was just to make state modification an explicit action, instead of just a variable modification.

28 remaining items

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

Metadata

Metadata

Assignees

Type

No type

Projects

Status

🆕 Triaging

Milestone

No milestone

Relationships

None yet

    Development

    Participants

    @8bitDesigner@posva@dakt@seangwright@stephane303

    Issue actions

      Add an option to disallow direct state modification from component · Issue #58 · vuejs/pinia