Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

1.9K
Visualizações
Vuex, update property of object in array causes many mutation methods

Let's say you have a store like this. And a component where you select a car from the list which gets passed as a prop to another component where you can edit various properties of the car object.

If the car objects had more properties like brand, weight etc. I would have to either:

  • Create a new mutation for every property This has the downside of causing a huge amount of mutations, which will make the store file very unreadable in my opinion.

  • Create a generic mutation that takes an object, a field, and a value and assign that. This has the benefit of only having one generic mutation. But it has the downside that it can't handle nested objects.

  • Create a new car object in the component and replace that in the state by id field. This feels like a clean solution but it would involve copying the object to remove mutability, and that feels less clean. And also slow down the app if use a lot I guess.

In my projects, I've ended up with a mix of these options which just feels chaotic.

So, my question is if there's a better pattern to use than any of these? And if not, which is considered the best practice. I've searched for an answer to this for a long time but never found any good explanation.

state: {
    cars: [
        {id: 1, color: "blue"},
        {id: 2, color: "blue"},
        {id: 3, color: "blue"},
    ]
},
mutations: {
    setColor(state, {car, color}){
        car.color = color;
    }
},
getters: {
    allCars(state){
        return state.cars;
    }
},
over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

I would do it using deepMerge function:

export const mutations = {
  setCarProperties(state, car) {
    const index = state.cars.findIndex((item) => item.id === car.id);

    Vue.set(state.cars, index, deepMerge(state.cars[index], car));
  }
};

So you can change and add properties (even nested):

updateCarType() {
  const car = {
    id: 2,
    type: {
      engine: "electric",
    },
  };
  this.$store.commit("setCarProperties", car);
},

Please note I am using Vue.set in mutation. You may wonder why I don't change state like usually we do:

state.cars[index] = deepMerge(state.cars[index], car));

But that won't be reactive, so Vue.set is needed. https://vuejs.org/v2/api/#Vue-set

Check demo: https://codesandbox.io/s/questions-69864025-vuex-update-property-of-object-in-array-causes-many-mutation-methods-sq09z?file=/pages/index.vue

over 4 years ago · Santiago Trujillo Relatório

0

I will share my views on this subject. Sincerely I don't know the best practice, and there are a handful of variations of the same approach.

Basically, it applies only the second principle you mentioned, and keeps the reactivity in place for the whole update cycle.

In the store make a generic mutation:

mutations: {
    setItem(state, item) {
      let idx = state.items.findIndex((i) => i.id === item.id);
      Vue.set(state.items, idx, item);
    }
}

In component map the state items to a computed property, and make another one for the edited item:

computed: {
    ...mapGetters({ allItems: "allItems" }),
    localItem: {
      get() {
        return this.allItems[0];
      },
      set(val) {
        this.setItem(val);
      },
    },
},
methods: {
    ...mapMutations(["setItem"])
}

And the tricky part, update the local item:

methods: {
    ...mapMutations(["setItem"]),
    changeItem() {
      this.$set(this, "localItem", { ...this.localItem, color: "red" });
    },
}

Do not update directly object properties but rather assign the whole object, so that the computed setter is triggered and changes are committed to store, without any warnings.

Codesandbox

over 4 years ago · Santiago Trujillo Relatório

0

You can pass whole car object, with changed properties, to action:

async carUpdate({ commit }, car) {
  await // some axios or fetch call...
  commit('updateCar', car);
},

then commit mutation like:

updateCar(state, car) {
  state.cars = [
    ...state.cars.map((item) =>
      item.id !== car.id
        ? item
        : {
            ...item,
            ...car,
          }
    ),
  ];
},
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda