Skip to content
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

[Vuex] Store.commit() persists all pending changes on object lists, even if method does nothing #2203

Closed
enloc-port opened this issue Dec 23, 2022 · 4 comments
Labels
3.x question This is a question rather than an issue or pull request

Comments

@enloc-port
Copy link

enloc-port commented Dec 23, 2022

Version

Vue: 2.6.14
Vuex: 3.5.1

Description

We did not find any documentation of the behavior we encountered with the store's commit() method when working with a list of objects, so we do not know what to make of it.

It seems like any call to commit() persists all pending changes to the state, even if the method called in commit() does not do anything.

In the example below, when editing one of the fields and clicking "Commit nothing", the changes are persisted in the state, even though the store's doNothing() method did not do anything.

The Vuex "Mutations" page does not address this at all, hence we wonder, is this a bug or intended behavior?
In case of the latter, it should be documented and emphasized on the "Mutations" page, because it is very unintuitive.

Example

example.vue

<template>
  <div>
    <div>
      <input v-model="computedObject.string"/>
      <input type="number" v-model="computedObject.number"/>
    </div>

    <div>
      <div>computedObject.string: {{ computedObject.string }}</div>
      <div>computedObject.number: {{ computedObject.number }}</div>
    </div>
    
    <button @click="clearList">Clear list</button>
    <button @click="resetList">Reset list</button>
    <button @click="commitNothing">Commit nothing</button>
  </div>
</template>

<script>
export default {
  name: "example",
  methods: {
    clearList() {
      this.$store.commit("clearList");
    },
    resetList() {
      this.$store.commit("resetList");
    },
    commitNothing() {
      this.$store.commit("doNothing");
    },
  },
  computed: {
    computedObject() {
      return this.$store.state.someList.at(-1) ?? {};
    },
  },
}
</script>

store.js

import Vue from "Modules/vue";
import Vuex from "Modules/vuex";

Vue.use(Vuex);

export default new Vuex.Store({
    state: {
        someList: [{
            string: "Hello World!",
            number: 123,
        }],
    },
    
    mutations: {
        clearList(state) {
            state.someList = [];
        },

        resetList(state) {
            state.someList = [{
                string: "Hello World!",
                number: 123,
            }];
        },

        doNothing() {
            console.log("I did nothing.");
        },
    },
});
@enloc-port enloc-port changed the title Store.commit() persists all pending changes, independent from anything else Store.commit() persists all pending changes on object lists, independent from anything else Jan 3, 2023
@enloc-port enloc-port changed the title Store.commit() persists all pending changes on object lists, independent from anything else [Vuex] Store.commit() persists all pending changes on object lists, independent from anything else Jan 3, 2023
@enloc-port enloc-port changed the title [Vuex] Store.commit() persists all pending changes on object lists, independent from anything else [Vuex] Store.commit() persists all pending changes on object lists, even if method does nothing Jan 3, 2023
@enloc-port
Copy link
Author

Can anyone at least confirm that this is a thing and maybe say whether it's a bug or a feature?

@enloc-port
Copy link
Author

@yyx990803 @kiaking If you cannot say anything about this, would you mind telling me who to contact in order to get a reaction to this issue?

@cuebit
Copy link
Member

cuebit commented Jan 30, 2023

This is neither a feature or a bug.

You're mutating the state directly. You can verify this claim by enabling strict mode and observing the console error when modifying the model value.

In your example, a shallow object can be spread into a new object as to avoid this conflict, for example:

computedObject() {
  return { ...this.$store.state.someList.at(-1) };
}

@cuebit cuebit added question This is a question rather than an issue or pull request 3.x labels Jan 30, 2023
@cuebit
Copy link
Member

cuebit commented Feb 13, 2023

Feel free to file a new issue if you discover anything else 👍

@cuebit cuebit closed this as completed Feb 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.x question This is a question rather than an issue or pull request
Projects
None yet
Development

No branches or pull requests

2 participants