What reasons could be preventing the state from updating correctly in Vuex?

Currently, I am working on a project where I am utilizing vuex along with axios to retrieve data from the backend. The issue arises when I try to access the state - even though the updated state is displayed successfully when I console-log it, there seems to be no data available when I attempt to call the state directly. Can anyone point out what might be causing this discrepancy?

Vuex File

import axios from "axios"; 
import { uid } from "quasar";

const state = {
  data: {},
};

const mutations = { 
  addData(state, payload) {
    state.data[payload.id] = payload.data;
    console.log(state.data); //the data exist
  },
};



 const actions = {
      readData({ commit }) {
        axios({
          method: "get",
          url:
            "https://dev.activate.vi9e.com/api/purchase/receivegoods/index?action=list",
          headers: {
            "Content-Type": "application/json",
          },
        })
          .then((response) => {
            for (var i = 0; i < response.data.length - 1; i++) {
              let dataId = uid();
              let payload = {
                id: dataId,
                data: response.data[i],
              };
              commit("addData", payload);
            }
          })
          .catch((error) => {
            //handle error
            console.log("error message: ", error.message);
          });
      },
    };

const getters = {
  data: (state) => {
    return state.data;
  },
};

export default {
  namespaced: true,
  state,
  mutations,
  actions,
  getters,
};

This is how my template looks like:

<template>
  <p>{{ data }}</p>
</template>

<script>
import { mapGetters, mapActions } from "vuex";

export default {
  methods: {
    ...mapActions("incominggoods", ["readData"]),
  },
  computed: {
    ...mapGetters("incominggoods", ["data"]),
  },
  mounted() {
    this.readData();
  }

};
</script>

Despite the fact that I can see the data in mutations via console-logging, the state's data does not seem to update at all. How can I address this issue?

SOLUTION I appreciate all the helpful comments provided so far. They have been instrumental in addressing this problem. It appears that the root cause lies in Vue's reactivity behavior. Vue doesn't inherently support handling non-primitive data types such as objects and arrays when assigning these directly to the state object. Based on the feedback received, here is how I tackled the situation:

  1. I manually manipulated the incoming data from the backend (which was in object form) and converted it into Object datatype.

In actions (inside then(response))

for (var i = 0; i < response.data.length; i++) {
          let dataId = uid();

         // manipulate the "object" to "Object"
          let data = {
            poid: response.data[i].purchase_order_id,
            podate: response.data[i].po_date,
            vendor: response.data[i].vendor_name,
            qty: "0%",
            total_qty_ordered: response.data[i].total_qty_ordered,
            total_qty_receivable: response.data[i].total_qty_receivable,
            total_qty_received: response.data[i].total_qty_received,
            status: response.data[i].status,
            barcode: response.data[i].purchase_order_id,
            printed_id: response.data[i].printed_id,
          };
// END OF THE MANIPULATION 

          let payload = {
            id: dataId,
            data: data,
          };
          commit("addData", payload);

In mutations

addData(state, payload) {
    Vue.set(state.data, payload.id, payload.data);
  },

Answer №1

When it comes to JS reactivity, dealing with non-primitive types like objects and arrays can be a bit peculiar (further explained in the text). Think of an object as a bus with tinted windows. If passengers (items in an array or key/value pairs in an object) come and go on the bus and you were observing from the outside, you wouldn't see any changes - the bus would still appear the same. This analogy captures how reactivity works in JavaScript, giving you two options for handling object reactivity.

You can choose to either:

a) completely replace the entire object

b) use Vue.set in the case of Vue (for objects specifically, not for arrays)

For option a), the code looks like this:

// for objects
const addObjectProperty = (state, property) => {
  state.object = {...state.object, property)
}
// for arrays
const addArrayItem = (state, item) => {
  state.array = [...state.array, item]
}

What happens here is that a new object is created on-the-fly using object literal syntax ({ } or [ ]). By doing this, Vue recognizes the change in your state.object and reacts accordingly.

Option b) involves using Vue.set as shown below:

const addObjectProperty = (state, property) => {
  // Vue.set params: object, key, value 
  Vue.set(state.object, state.object[property], property)
}

For arrays, stick to using array methods instead of manually altering values like arr[x] = 10, which can lead to the same reactivity issue.

Additionally, if you have a nested object within a state property, remember that you must still replace the top-level object.

state: {
  this: {},
  is: {},
  what: {},
  you: {},
  need: {},
  to: {},
  change: {},
  not: {
    this: {}
  }
}

If you are dealing with complex nested states, consider utilizing vuex modules as a convenient approach.

Answer №2

Vue's reactivity system may not pick up on the addition of object properties, as explained in more detail here.

When making changes to your data, replace this

state.data[payload.id] = payload.data;

with the following:

Vue.set(state.data, payload.id, payload.data);

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

RxJS - Only emit if another source does not emit within a specified time frame

Imagine having two observables. Whenever the first one emits, there should be a 2-second pause to check if the other observable emits something within that timeframe. If it does, then no emission should occur. However, if it doesn't emit anything, the ...

Exploring NodeJS Express Routing Across Various URIs/URLs

In my application, there is a public folder that contains HTML/CSS3/JS code. This folder has two main parts: one with the public facing index.html inside public/web and another with an admin view exclusively for admins. Below is the basic layout: public ...

Experiencing challenges in integrating fundamental Javascript elements on a chat page

My chat page skeleton is in place, but I'm facing challenges in connecting all the pieces. My goal is to send messages to the server whenever a user clicks 'send', and to update the displayed messages every 3 seconds. Any insights, tips, or ...

Can you explain the distinction between using get() and valueChanges() in an Angular Firestore query?

Can someone help clarify the distinction between get() and valueChanges() when executing a query in Angular Firestore? Are there specific advantages or disadvantages to consider, such as differences in reads or costs? ...

Unable to retrieve information using the post method in Express framework

After creating a basic code to fetch data from the client, I am facing an issue where req.body.firstname is showing as undefined. Here is the code snippet: const express = require('express'); const app = express(); const body ...

Guidance on invoking the navigate function from a component displayed at the highest level of rendering

Within the react-navigation documentation, it is explained that you can initiate navigation from the top-level component using the following method: import { NavigationActions } from 'react-navigation'; const AppNavigator = StackNavigator(SomeA ...

Sending form data without interrupting the user interface by using asynchronous submission

Using jQuery version 1.7.2, I am currently using the submit() method to send a form via POST. This triggers a Python cgi-bin script that performs some tasks which may take around ten seconds to finish. Upon completion of the task, the Python script instruc ...

Troubleshooting Angular: Unidentified property 'clear' error in testing

I've implemented a component as shown below: <select #tabSelect (change)="tabLoad($event.target.value)" class="mr-2"> <option value="tab1">First tab</option> <op ...

How can an array of file paths be transformed into a tree structure?

I am looking to transform a list of file and folder paths into a tree object structure (an array of objects where the children points to the array itself): type TreeItem<T> = { title: T key: T type: 'tree' | 'blob' childr ...

"Learn the process of setting a variable in ng-model within an input field based on a specific condition

I need to dynamically assign an ng-model variable based on a condition. For instance: <input type="text" ng-model="item.model[multilang]" > The $scope.multilang variable can be set to either "ENG", "JP" (languages) or false. So, when multilang = "E ...

Using Jquery, insert a line break when a specific character is entered in a text area by pressing the Enter button

$('.text-description').keyup(function () { var count = $(this).val().length; if(count == 63){ //insert line break here } }); When the character count reaches 63, including spaces, I want the cursor to move to the next line (sim ...

Top method for identifying browser window modifications such as navigating back, altering the URL, refreshing, or closing the window

Currently, I am developing a testing application that requires me to trigger a finsihTheTest() function in specific situations. These situations include: When the user attempts to reload the page. When the user tries to navigate back from the page. If the ...

Guide on transforming Div content to json format with the use of jquery

I am trying to figure out how to call the div id "con" when the export button is clicked in my HTML code. I want it to display JSON data in the console. If anyone has any suggestions or solutions, please help! <html> <div id ="con"> < ...

Flowbite components are visually appealing, but unfortunately, the interactions are not functioning properly

I am experiencing issues with all flowbite components. The problem lies in the fact that while the components load, the interactions do not work. For example, this accordion remains open and I am unable to close or open it. Similarly, the modals and carou ...

The loading cursor in IE7 flickers incessantly, causing the webpage to lag and become un

When I move my cursor and click in text fields, the page becomes unresponsive and shows a wait cursor. If you're curious to see this issue in action, check out this video. This problem is specific to IE7. I've attempted to identify any ajax re ...

The best way to avoid routing before certain async data in the Vuex store has finished loading

I am facing a challenge in my application where I require certain data to be loaded into the VueX store before routing can commence, such as user sessions. An example scenario that showcases a race condition is as follows: // Defined routes { name: &ap ...

Building a Vuetify Form using a custom template design

My goal is to create a form using data from a JSON object. The JSON data is stored in a settings[] object retrieved through an axios request: [ { "id" : 2, "name" : "CAR_NETWORK", "value" : 1.00 }, { "id" : 3, "name" : "SALES_FCT_SKU_MAX", "val ...

Display Quantity of Current Website Visitors

Similar Question: how to track website visitors using java script or php I am looking to retrieve the current number of viewers on a webpage that has an embedded stream. Is there a method to accomplish this utilizing PHP and AJAX, in order to display ...

The networking feature stops functioning on Android devices after upgrading from Ionic 1.5.0 to 1.6.3

After upgrading from ionic 1.5.0 to 1.6.3 (the latest version), I noticed that networking ajax calls were no longer working on Android. I had to remove and re-add the android platform, and there seemed to be a change in the apk names from MainActivity-debu ...

Contrast 2 GET objects retrieved from separate controllers

I have 2 collections of data from different controllers. Data Collection 1 (Controller Name): [{id:1,"name":"jakov"},...] Data Collection 2 (Controller Nickname): [{id:1, "nickname" : "jandric", "nameId" :1, "title" : "master"},...] I send data from C ...