Search code examples
vue.jsvuejs2vue-componentvuexv-for

Vue and Vuex v-for not updating properly when state changes


Here is my store and delete mutation.

const store = new Vuex.Store({
  state: {
    todos: [
      {
        date: "22/03/1994",
        todos: [
          { icon: 0, text: "seyehate çıkılacak " },
          { icon: 0, text: "seyehate çıkılacak " },
        ]
      },
      .....
    ]
  },

  getters: {
    getTodos: state => {
      return state.todos
    }
  },

  mutations: {
     delete(state, { dateIndex, index }) {
      console.log("dateIndex", dateIndex)
      if (state.todos[dateIndex].todos.length == 1) {
        state.todos.splice(dateIndex, 1)
      } else {
        state.todos[dateIndex].todos.splice(index, 1)
      }
    }
  },
})

This is my main component:

<ListDate
  v-for="(item, index) in list"
  :key="index"
  :todos="item"
  :dateIndex="index"
></ListDate>

And I computed data with getters:

computed: {
  list() {
    return this.$store.getters.getTodos;
  },
},

and in my ListDate component:

<ListItem
  v-for="(item, index) in dateTodos"
  :key="index"
  :message="item.text"
  :icon="item.icon"
  :dateIndex="dateIndex"
  :index="index"
/>

In this component I commit delete mutation. Its work but when I splice with dateIndex its not work correct. I look state and I see its changed but list not render as correct way. when I delete some index suddenly last object gone, state is normal but view not look correct. how I render state data correctly?


Solution

  • Since your v-for uses index as a key, when you delete an item, the next one slides into its place, and the DOM is reused.

    You need to create a truly unique property on the objects to use as a key, like an id:

    todos: [
      { id: 1, icon: 0, text: "seyehate çıkılacak " },
      { id: 2, icon: 0, text: "seyehate çıkılacak " },
    ]
    

    And use that property as the key:

    <ListItem
      v-for="(item, index) in dateTodos"
      :key="item.id"
      :message="item.text"
      :icon="item.icon"
      :dateIndex="dateIndex"
      :index="index"
    />