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

Guide to incorporating rate-limiter-flexible into your current node.js express configuration

I am currently using node.js, passport, and JWT bearer token for securing my routes. However, I have yet to implement rate limiting and IP/user blocking for too many false login attempts. What is the recommended approach to integrate this into my existing ...

JQuery Submission with Multiple Forms

Hey everyone! I have a jQuery form with multiple fieldsets that switch between each other using jQuery. Eventually, it leads to a submit button. Can someone assist me by editing my jfiddle or providing code on how I can submit this data using JavaScript, j ...

Tips for arranging imports in a Vue file

While Prettier formats my code, it does not organize the order of imports. In Go using VS Code, Gofmt automatically reorders imports in the correct order. How can I achieve a similar functionality for organizing Vue imports in VS Code? ...

Animating a CSS shape with the .animate method

I need help creating a dynamic graphic for my school project using css, jquery, and html. I want to make a rectangle that moves across the screen, but I'm having trouble getting it to work properly. Despite trying different variations of the animate f ...

Addressing the issue of prolonged Electron initialization

Scenario After spending considerable time experimenting with Electron, I have noticed a consistent delay of over 2.5 seconds when rendering a simple html file on the screen. The timeline of events unfolds like this: 60 ms: app ready event is triggered; a ...

Steps to activate checkbox upon hyperlink visitation

Hey there, I'm having a bit of trouble with enabling my checkbox once the hyperlink has been visited. Despite clicking the link, the checkbox remains disabled. Can anyone provide some guidance on how to get this working correctly? <script src=" ...

How can you dynamically change the value of a React datetime slider picker using code?

I can't figure out how to programmatically update the value of the React datetime slider picker, especially when I click on a button. The rendering code for the widget looks like this: <RDSPwidget enableSecond={true} /> This is how my ...

Is there a way to automatically extract data from a CSV file and display it on a website using either PHP or JavaScript?

I have a web service link at www.xyz.com/abcdefg. When I visit this link, it automatically downloads a CSV file. The CSV file contains columns of data organized like this: Column A Column B Column C Column D test1 1 5 ...

Removing duplicate values in Vue after sorting

Explore <div v-for="todo in sortedArray"> <b-button block pill variant="outline-info" id="fetchButtonGap" v-model:value="todo.items[0].arrivalTime"> {{fromMilTime(todo.items[0].arrivalTime)}} < ...

Is it possible for a component to identify its child routes within vue-router?

<Main> <router-view></router-view> </Main> [ { path: '/', component: Intro, }, { path: '/path1', component: Main, children: [{},{},{}] }, { path: '/path2', comp ...

The function Object.defineProperties() allows for reassigning a property's value after it has been initially

The issue arises in the initial code snippet provided below, specifically when dealing with the object book. Initially, the value of book.year is set to 2013. Even after updating the value by setting book.year = 2015, retrieving the value using book.year s ...

Display a tooltip for ever-changing content

My HTML code displays dynamic rows with information, along with an image link that reveals specific details about the clicked row using the compentence_ID field. echo "<td>".$compi['Competence_ID']."</td>"; ec ...

Experiencing difficulties coding SVGs

Struggling with manipulating SVGs in JavaScript and looking to extend a line by clicking a button? Check out this code snippet I've included in the head tag: <script type="text/javascript"> x=135; y=135; var container = document.getElementById( ...

Node.js equivalent of the `Pattern.compile` function

This Java/Android code works perfectly to extract all text between <tag> and </tag> What is the equivalent of this Java code in Node.js/Javascript? private static final Pattern TAG_REGEX = Pattern.compile("<tag>(.+?)</tag>"); pri ...

Passing ngModel from controller to directive in AngularJS

I'm currently working on a project that involves a controller with an attribute directive nested inside of it. This directive requires access to the ngModel of its parent controller. For more context, feel free to check out this Plunkr. Issue at Han ...

The process for changing the textContent to X when an image is clicked

How can I create a function that changes the text content to 'X' when an image is clicked? I already have a function that updates the title based on the image dataset, but combining the two functions has been unsuccessful. Can someone help me con ...

Is it possible to create two header columns for the same column within a Material UI table design?

In my Material UI table, I am looking to create a unique header setup. The last column's header will actually share the same space as the previous one. Picture it like this: there are 4 headers displayed at the top, but only 3 distinct columns undern ...

Instructions for utilizing lodash or JavaScript to apply a filter to an object

Received this object from the Server: var data = { test1: { documents: [] }, test2: { documents: [{ vId: 'sdfas23', TypeId: '81', isDeleted: false }], answer: true }, test3: { documents: ...

The React JSX error message "Maximum update depth exceeded" occurs when there

It appears that I am facing an issue of creating an infinite loop while passing props from one class to another. Despite ensuring that the buttons are correctly bound and trigger only once, the problem persists without any solution in sight after thorough ...

Tips for executing Cross-Origin-Requests from Firebase Hosting to an AWS Lambda function

Excuse me, I'm still new to web development. I have a basic single-page website hosted on Firebase hosting that retrieves some information from an AWS Lambda function (I didn't use Google Cloud because it didn't support outbound requests fo ...