Philipp Chapkovski
Philipp Chapkovski

Reputation: 2059

can I set several state params with one mutation in Vuex?

I have a store with several state parameters and some (not all!) should be reset to their initial values.

I wonder if I can have one mutation to change several keys in vuex or is it a bad practice?

So it would look like that:

const store = new Vuex.Store({
    state: {
        a: 0,
        b: 2,
        c: 1,
        
        z: 0
},
     mutations: {
        RESETALL: (state) => {
            state.a = 0;
            state.b = 2;
            ...
            state.z = 0;
        },

Upvotes: 0

Views: 658

Answers (3)

Nathan Strutz
Nathan Strutz

Reputation: 8123

The short answer is Yes. You can, and should, change multiple state parameters in a single mutation.

  • this saves you time
  • this saves you from typing many lines of code
  • this models your application in a nice way

What do I mean by that last point? Instead of an action that does this:

async loadData() {
  commit("setLoading", true);
  commit("setData", []);
  commit("setError", "");
  const newData = await axios.get("/data");
  commit("setData", newData);
  commit("setLoading", false);
}

You could have an action that expresses what it's doing and why:

async loadData() {
  commit("loadingData");
  const newData = await axios.get("/data");
  commit("applyNewlyLoadedData", newData);
}

The mutations then look like:

loadingData = (state) => {
  state.loading = true;
  state.data = [];
  state.error = "";
},
applyNewlyLoadedData = (state, payload) => {
  state.data = payload;
  state.loading = false;
},

This leads to simpler actions (which I typically see grow into complex beasts), and slightly more complex mutations (which typically do very little and make the mutation layer much more useless than it need be).

Upvotes: 3

Arsa
Arsa

Reputation: 76

Mutation have the access to the whole state object, you can mutate(init, set, clear) the whole state if you want..

Upvotes: -1

Lawrence Cherone
Lawrence Cherone

Reputation: 46602

You could make an init, set, clear etc, for example:

import Vue from 'vue'

/**
 * State for thing
 *
 * Usage: this.$store.state.thing.*
 */
const defaultState = {
  someDefaultProp: true,
  foo: null,
  bar: null
}
export const state = () => ({
   ...defaultState
})

/**
 * Mutations / Setters
 *
 * Usage: this.$store.commit('thing/<method name>', payload)
 */
export const mutations = {
  /**
   * Initialize/hydrate state
   *
   * Usage: this.$store.commit('thing/init', {id: 123})
   *
   * @param {Object} state
   * @param {Object} data
   */
  init (state, data) {
    // hydrate passed vars
    for (const i in data) {
      Vue.set(state, i, data[i])
    }
  },

  /**
   * Set single state item
   *
   * Usage: this.$store.commit('thing/set', {key: 'id', value: 123})
   *
   * @param {*} state
   * @param {*} param1
   */
  set (state, {
    key,
    value
  }) {
    Vue.set(state, key, value)
  },

  /**
   * Clear state, set to null
   * @param {*} state
   */
  clear (state) {
    // set all to null
    for (const i of Object.keys(state)) {
      state[i] = typeof defaultState[i] === 'undefined' ? null : defaultState[i]
    }
  }
}

Then use like:

  • init: this.$store.commit('thing/init', {foo: 123, bar:'baz'})
  • set: this.$store.commit('thing/set', {key: 'bar', value: 'boo'})
  • clear this.$store.commit('thing/clear')

Upvotes: 1

Related Questions