Skip to content
Advertisement

How to design a store in Vuex to handle clicks in nested, custom components?

I’m trying to design a store to manage the events of my Vuex application. This far, I have the following.

import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);

const state = { dataRows: [], activeDataRow: {} };
const mutations = {
    UPDATE_DATA(state, data) { state.dataRows = data; state.activeDataRow = {}; },
};

export default new Vuex.Store({ state, mutations });

I’m going to have a number of list items that are supposed to change the value of the data in the store when clicked. The design of the root component App and the menu bar Navigation is as follows (there will be a bunch of actions in the end so I’ve collected them in the file actions.js).

<template>
  <div id="app">
    <navigation></navigation>
  </div>
</template>
<script>
import navigation from "./navigation.vue"
export default { components: { navigation } }
</script>

<template>
  <div id="nav-bar">
    <ul>
      <li onclick="console.log('Clickaroo... ');">Plain JS</li>
      <li @click="updateData">Action Vuex</li>
    </ul>
  </div>
</template>
<script>
  import { updateData } from "../vuex_app/actions";
  export default {
    vuex: {
      getters: { activeDataRow: state => state.activeDataRow }, 
      actions: { updateData }
    }
  }
</script>

Clicking on the first list item shows the output in the console. However, when clicking on the second one, there’s nothing happening, so I’m pretty sure that the event isn’t dispatched at all. I also see following error when the page’s being rendered:

Property or method “updateData” is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.

I’m very new to Vuex so I’m only speculating. Do I need to put in reference to the updateData action in the store, alongside with state and mutations? How do I do that? What/where’s the “data option” that the error message talks about? Isn’t it my components state and it’s properties?

Advertisement

Answer

Why the error

You are getting the error, because when you have <li @click="updateData"> in the template, it looks for a method updateData in the vue component which it does not find, so it throws the error. To resolve this, you need to add corresponding methods in the vue component like following:

<script>
  import { updateData } from "../vuex_app/actions";
  export default {
    vuex: {
      getters: { activeDataRow: state => state.activeDataRow }, 
      actions: { updateData }
    }, 
    methods:{ 
      updateData: () => this.$store.dispatch("updateData")    
    }
  }
</script>

What this.$store.dispatch("updateData") is doing is calling your vuex actions as documented here.

What/where’s the “data option”

You don’t have any data properties defined, data properties for a vue component can be used, if you want to use that only in that component. If you have data which needs to be accessed across multiple components, you can use vuex state as I believe you are doing.

Following is the way to have data properties for a vue component:

<script>
  import { updateData } from "../vuex_app/actions";
  export default {
    date: {
      return {
        data1 : 'data 1',
        data2 : {
            nesteddata: 'data 2' 
          }
      }
    }
    vuex: {
      getters: { activeDataRow: state => state.activeDataRow }, 
      actions: { updateData }
    }, 
    methods:{ 
      updateData: () => this.$store.dispatch("updateData")    
    }
  }
</script>

You can use these data properties in the views, have computed properies based on it, or create watchers on it and many more.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement