Search code examples
javascriptarraysvuexvuejs3

How to loop over an array from the vuex store


I'm using vuex and vuejs 3 and I'm trying to loop over an array from the vuex store butt it keeps throwing an error saying the array is undefined. I tried loging the data and it is working but when using it with the v-for directive it says it's undefined here's the store

import { createStore } from 'vuex'

export default createStore({
  state: {
    AddTaskShown: false,
    Tasks: []
  },
  getters: {
  },
  mutations: {
      ToggleAddTask(state) {
      state.AddTaskShown = !state.AddTaskShown;
    },
    addTask(st, {name, description, date }) {
      st.Tasks = [...st.Tasks, {name, description, date}]
    },
  },
  actions: {
  },
  modules: {
  }
})

and here's the component

<template>
  <div class="grid grid-cols-1 gap-1 py-3">
    <Task :v-for="Task in $store.state.Tasks" :Task="Task" />
  </div>
</template>

<script>
import Task from "@/components/Task.vue";

export default {
  components: {
    Task,
  },
};
</script>

and the child component ( the one I'm looping)

<template>
<div class="mx-5 my-1 bg-slate-700 p-4 text-white rounded-lg">
    <input type="checkbox" class="w-4 h-4 mr-2"> {{ Task.name }}
</div>
</template>
<script>
export default {
  name: "Task",
  props: {
    Task: Object,
  },
};
</script>```
and it gives me an error saying
```Task.vue?c155:2 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'name')
    at Proxy.render (Task.vue?c155:2:1)
    at renderComponentRoot (runtime-core.esm-bundler.js?d2dd:896:1)
    at ReactiveEffect.componentUpdateFn [as fn] (runtime-core.esm-bundler.js?d2dd:5580:1)
    at ReactiveEffect.run (reactivity.esm-bundler.js?89dc:185:1)
    at instance.update (runtime-core.esm-bundler.js?d2dd:5694:1)
    at setupRenderEffect (runtime-core.esm-bundler.js?d2dd:5708:1)
    at mountComponent (runtime-core.esm-bundler.js?d2dd:5490:1)
    at processComponent (runtime-core.esm-bundler.js?d2dd:5448:1)
    at patch (runtime-core.esm-bundler.js?d2dd:5038:1)
    at mountChildren (runtime-core.esm-bundler.js?d2dd:5234:1)```

Solution

  • You need to use set the Tasks state in a computed property to watch the changes happen to the state, it gives error, because the template executes before the Tasks state initialize.

    Also, there is another issue which is a naming conflict between the component name Task and the single array item Task.

    You need to update the props name to task instead of Task

    It would be better to always name your variables as camelCase

    <template>
    <div class="grid grid-cols-1 gap-1 py-3">
        <Task :v-for="task in Tasks" :task="task" />
      </div>
    </template>
    
    <script>
    import Task from "@/components/Task.vue";
    
    export default {
      components: {
        Task,
      },
      computed: {
         Tasks() {
             return this.$store.state.Tasks
         }
      }
    };
    </script>