Vue component fails to react to updates from Vuex

Currently, I am developing a system to facilitate the management of orders at a shipping station. Although I have successfully implemented the initial changes and most of the functionality, I am encountering an issue where one component fails to update another despite confirming that the data is being updated.

Inserting some code snippet now

./store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
 state: {
   greenboard :{
     station: 1,
     incomplete_orders:[],
     complete_orders:[],
   },
   yellowboard:{
     incomplete_orders:[],
     complete_orders:[],
   },
   dashboard:{

   },
 },
 getters: {
   greenIncomplete: state => {
     return state.greenboard.incomplete_orders;
   },

   greenComplete: state => {
     return state.greenboard.complete_orders;
   },

   greenStation: state => {
     return state.greenboard.station;
   }
 },
 mutations: {
   updateGreenOrders (state,payload){
     state.greenboard.incomplete_orders = payload.incomplete_orders;
     state.greenboard.complete_orders = payload.complete_orders;
   },
   updateGreenStation (state,payload){
     Vue.delete(state.greenboard, 'station');
     Vue.set(state.greenboard, 'station', payload.station);
     console.log(state.greenboard)
   }
 },
 actions: {}
});

/app.js

/**
 * First we will load all of this project's JavaScript dependencies which
 * includes Vue and other libraries. It is a great starting point when
 * building robust, powerful web applications using Vue and Laravel.
 */

require('./bootstrap');

window.Vue = require('vue');


/**
 * The following block of code may be used to automatically register your
 * Vue components. It will recursively scan this directory for the Vue
 * components and automatically register them with their "basename".
 *
 * Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
 */

// const files = require.context('./', true, /\.vue$/i)
// files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default))

Vue.component('example-component', require('./components/ExampleComponent.vue').default);
Vue.component('green-orders', require('./components/GreenOrders.vue').default);
Vue.component('stations-nav', require('./components/StationsNav.vue').default);
Vue.component('green-board', require('./components/GreenBoard.vue').default);
Vue.component('order-card', require('./components/OrderCard.vue').default);

/**
 * Next, we will create a fresh Vue application instance and attach it to
 * the page. Then, you may begin adding components to this application
 * or customize the JavaScript scaffolding to fit your unique needs.
 */
import store from "./store";
const app = new Vue({
    store,
    el: '#app',
});

StationsNav.vue

<template>
...
</script>

GreenOrders.vue

<template>
...
</script>

GreenBoard.vue

<template>
...
</script>

For a visual representation of the rendered code, refer to this screenshot https://i.stack.imgur.com/HXTho.jpg

After selecting the second station and updating the store in index.js, clicking the "button" word logs out the correct station. However, the orders do not get updated based on the selected station. Instead, they continue to display orders from the default station. I believe I might be overlooking something as a newcomer to VUE, but familiar with JavaScript. Watchers or actions in Vuex could be the missing link, but I am open to any guidance. Thank you for your assistance in advance.

Answer №1

After encountering a problem with understanding how actions work in Vuex, I realized that the async call was not triggering the repaint of the orders. In order to handle asynchronous tasks, it is essential to use actions in Vuex. Actions allow for handling scenarios like calling an API and waiting for the response before updating the state using mutations, which are reactive in Vuex. This required me to convert a significant portion of my local data into computed properties and retrieve information from the storage directly instead of relying on getters to populate the local storage.

This adjustment also enabled me to properly utilize the vuex storage in the station nav component.

Below, you can find the modified files that now function as expected.

/store/index.js


import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    greenboard :{
      station: 1,
      incomplete_orders:[],
      complete_orders:[],
    },
    yellowboard:{
      incomplete_orders:[],
      complete_orders:[],
    },
    dashboard:{

    },
  },
  getters: {
    greenIncomplete: state => {
      return state.greenboard.incomplete_orders;
    },

    greenComplete: state => {
      return state.greenboard.complete_orders;
    },

    greenStation: state => {
      return state.greenboard.station;
    }
  },
  mutations: {
    updateGreenOrders (state,payload){
      console.log(payload);
      state.greenboard.incomplete_orders = payload.incomplete_orders;
      state.greenboard.complete_orders = payload.complete_orders;
      state.greenboard.station = payload.station;
    },
    updateGreenStation (state,payload){
      Vue.delete(state.greenboard, 'station');
      Vue.set(state.greenboard, 'station', payload.station);
    }
  },
  actions: {
    async updateGreenOrders(context,payload){
      try{
        const incomplete = await axios.get('/internal/green-orders/'+payload.station+'/0/');
        const complete = await axios.get('/internal/green-orders/'+payload.station+'/1/');
        context.commit({
          type:"updateGreenOrders",
          incomplete_orders: incomplete.data.data,
          complete_orders:complete.data.data,
          station:payload.station
        });
      }catch(e){
        console.log(e);
      }
    }
  }
});

StationsNav.vue

<template>
  <ul>
    <li v-for="station in stations" v-bind:key="station.id" v-on:click="stationChange(station.id)">{{station.station_name}}<br />{{station.description}}</li>
  </ul>
</template>

<script>
    export default {
      name:'StationsNav',
      components:{},
      data(){
          return {
            stations: [],
            chosen_station:0 ,
            error:"",
          }
      },
      created(){
        this.fetchStations();
      },

      methods:{
        async fetchStations(){
          try{
            const res = await axios.get('/internal/stations/');
            this.stations = res.data.data;
          }catch(e){
            console.log(e);
          }

        },

        stationChange(stationId){
          this.$store.dispatch({
            type:"updateGreenOrders",
            station:stationId
          });
        }
      },
      mounted() {

      }
    }
</script>

GreenOrders.vue

  <template>
    <div class="container-fluid">
      <!--button class="buton" v-on:click="debug">
        debug
      </button-->
      <div class="row justify-content-center">
        <div class="col-md">
          <h3>Green Orders Station {{station}}</h3>
          <p>
            These orders are referenced from the Woocomerce system for orders ready to be shipped.
          </p>
          <order-card
          v-on:orderstatuschange = "changeOrderStatus"
          v-for="order in orders_incomplete"
          v-bind:key="order.id"
          v-bind:id="order.id"
          v-bind:order_id = "order.order_id"
          v-bind:number_of_items = "order.number_of_items"
          v-bind:completion = "order.completion"
          ></order-card>
        </div>
        <div class="col-md">
          <h4>Monitor Completed Orders</h4>
          <p>
            Completed orders eventually fall out of the system once their status is updated in Woocomerce
          </p>
          <order-card
          v-on:orderstatuschange = "changeOrderStatus"
          v-for="order in orders_complete"
          v-bind:key="order.id"
          v-bind:id="order.id"
          v-bind:order_id = "order.order_id"
          v-bind:number_of_items = "order.number_of_items"
          v-bind:completion = "order.completion"
          ></order-card>
        </div>
      </div>

    </div>
  </template>

<script>
    export default {
      name:'OrdersDisplay',
      components:{},
      data(){
          return {
            error:"",
          }
        },
      computed: {
        orders_incomplete(){
          return this.$store.state.greenboard.incomplete_orders;
        },
        orders_complete(){
          return this.$store.state.greenboard.complete_orders;
        },
        station(){
          return this.$store.state.greenboard.station;
        }
      },
      created(){
        this.fetchOrders(this.station);
      },

      methods:{
        fetchOrders(station){
          this.$store.dispatch({
            type:"updateGreenOrders",
            station:this.station
          });
        },

        async changeOrderStatus(order){
           try{
             const res = await axios.post('/internal/order/'+order.id+'/'+order.status+'/');
             this.fetchOrders(this.station);
           }catch(e){
             console.log(e);
           }
        },

        intervalUpdate(){
          var s = this;
          setInterval(function () {
            s.fetchOrders(s.station);
          }, 1000);
        },

        debug(){
          console.log("I'M THE CREAM OF THE CROP!")
        }

      },

      mounted() {
        //this.intervalUpdate();
        //this.fetchIncomplete(this.station);
        //this.fetchComplete(this.station);
        //console.log(this.$store.state.greenboard.incomplete_orders);
      }
    }
</script>

GreenBoard.vue

<template>
  <div class="container-fluid">
    <div class="row">
      <div class="col-3">
        <stations-nav></stations-nav>
      </div>
      <div class="col-9">
        <green-orders></green-orders>
      </div>
    </div>
  </div>
</template>

<script>

    export default {
      name:'GreenBoard',
      components:{},
      data(){
          return {
          }
      },

      created(){

      },

      methods:{

      },
      mounted() {

      }
    }
</script>

Documentation that provided insight into the issue: https://vuex.vuejs.org/guide/actions.html#dispatching-actions-in-components

Conclusion

To simplify the problem for future reference, when using Vuex, ensure to use mutations for reactivity. For asynchronous operations, utilize actions following this cycle:

dispatch action -> action resolves -> commit results -> vue reacts.

If any experienced individuals have additional insights, please share. Special thanks to Decade Moon for pointing me in the right direction.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Vue: The issue of two components repeatedly invoking each other recursively

Issue Description In my Vue application, I am facing an issue with 2 components (HierarchyNodesList and HierarchyNode) that are calling each other recursively. The component tree structure looks something like this: HierarchyNodesList HierarchyNode ...

When the button is clicked, I would like to use JavaScript to toggle the visibility of a div, allowing it to open and

I am attempting to toggle a div using JavaScript when the open and close button is clicked. However, I have encountered an issue where the div disappears when the button is clicked, possibly due to post-back. var toggle = function () { var mydiv = d ...

What is the equivalent of jQuery's blur event in AngularJS?

I need to implement a functionality in AngularJS where any opened component is closed when clicking outside of it. Is there an existing Angular directive for handling blur events, or do I need to come up with a custom solution? ...

Transforming an interactive HTML webpage into React/JSX

Imagine a scenario where I have two files: example.html <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta charset="u ...

Is the use of addEventListener("load",... creating an excessive number of XmlHttpRequests?

Consider a scenario where you have the following JavaScript code running in a Firefox plugin, aimed to execute an XmlHttpRequest on a page load: function my_fun(){ var xmlHttpConnection = new XMLHttpRequest(); xmlHttpConnection.open('GET', ...

JavaScript's speciality - altering the Jquery fade in and fade out effect on Firefox browsers

Utilizing Jquery, I implemented a feature on a table where moving the mouse over a row changes its color. The Javascript code was specifically designed for IE7 and works flawlessly there. However, when tested in Firefox, the text fades along with the backg ...

Updating state using the react `setState()` function will automatically trigger a re-render

I am currently working on a large form using React and material-ui. The form implements two-way binding to update the state when input changes occur. Interestingly, changing any input field triggers updates in all components (as observed through TraceRea ...

Tips on integrating Codrops tutorial codes into a SilverStripe website project

Exploring the vast array of tutorials and code examples on the Codrops site has been an enlightening experience. Codrops Website I'm eager to incorporate some of these resources into my SilverStripe projects as well. SilverStripe CMS After learning h ...

Step-by-step guide to swapping an element with a textarea element using javascript

My current project involves creating a user profile that includes a text box where users can describe themselves. I've already implemented a separate page for editing the profile, but now I want to add a feature where users can hover over their descri ...

Image failed to load

Issue Encountered in Browser Console: https://static.food2fork.com/pastaallavodkaa870.jpg.jpg 404 While attempting to display the image on the browser, I am uncertain if the problem lies within my code or with food2fork. Code from index.js: // Alway ...

css effect of background image transitioning on mouse hover

Is there a way to have an element on my webpage with a background image that follows the movement of the mouse when hovered over? I want it to be similar to this website: This is the HTML code I currently have: <section id="home" data-speed="3" data-t ...

Steps to trigger a modal (bootstrap 5) in react upon clicking a cell within the Full Calendar interface

My goal is to trigger a modal window using Bootstrap 5 (not React-Bootstrap library) when clicking on a day in the FullCalendar Component in React. I attempted to access the modal by using jQuery's $, but encountered the error message "$ is not a fun ...

javascript Try again with async await

I am working with multiple asynchronous functions that send requests to a server. If an error occurs, they catch it and retry the function. These functions depend on data from the previous one, so they need to be executed sequentially. The issue I am facin ...

Can Vue.js be configured to reload specific components only?

Can a specific component be reloaded in a Vue component that contains multiple components? For example, if there is a component structured like this: Main component <template> <button>Button<button> <component1></component> ...

"Comparing the similarity and accessibility of using the same browser session with a Firefox or Chrome

I'm working on a solution to close and open the same session in my browser using a Firefox extension. The code I have currently closes the browser and then opens the last session, but it also opens another window which is not desired. I want to be abl ...

Turning off strict mode in the bundling process of React with webpack can be achieved by following

I'm facing an issue with my application. It works perfectly in all browsers except for IE, where it throws the following error: 0x800a0416 - JavaScript runtime error: Multiple definitions of a property not allowed in strict mode In my webpack.config ...

When executing a Javascript POST request to a PHP script, it succeeds when running on

I have a simple code that works fine on my website when the PHP file is linked as "/phpcode.php", but it fails to retrieve data when I place the JavaScript request on another site and use the full link. I am currently using GoDaddy as my hosting provider. ...

Managing Express Sessions: Best Practices

I am currently working on handling authentication sessions in a Node.js, Express, Passport app. Despite using express-session and registering new users, the authentication still doesn't work. Below is the code snippet for the local strategy: // Loca ...

Assistance with offsetting a jQuery drop down menu

This is the third jQuery script that I've been working on. While parts of it have been inspired by other scripts, I'm now focusing on implementing a specific feature. I've dedicated 4 hours to solving the issue of displaying the submenu on ...

Differences in Loading Gif Visualization Across Chrome, Safari, and Firefox

Having an issue with a loading image in Chrome, while it displays correctly in Safari and Firefox. In Chrome, I see two half-loading images instead of one whole image. Struggling to find a solution for this problem, any assistance would be greatly apprecia ...