Avoid having the state update repeatedly in Vue components after dispatching any updates

Stepping into the realm of Vue and Vuex, I find myself faced with a challenge. I am in the process of creating a customer list with multiple products. To make this possible, I have set up a customer array within my Vue component that includes a products array for adding multiple items. Upon saving a customer, I send it to the Vuex store and push it to the customer array in my state. However, an issue arises when I add a product item to the second customer, as Vue ends up adding the product items to all customers.

Vue Component

 data() {
    return {
      customer: {
        cus_name: ""
        cus_product: [
          {
            product_name: "",
          }
        ]
      }
    };
  },
  methods: {
    addProduct() {
      this.customer.cus_product.push({
        product_name: ""
      });
    },

    removeProduct(index) {
      this.customer.cus_product.splice(index, 1);
    },

    addCustomer() {
      this.$store.dispatch("addCustomer", this.customer);
    }
  }
};  

Vuex Store

const state = {
    customers: []
};


const mutations = {
    addCustomer(state, customerData) {
        state.customers.push(customerData);
    }
};

const actions = {
    addCustomer(vuexContext, customerData) {
        vuexContext.commit('addCustomer', customerData);
    }
};

Answer №1

When adding a new product using the addProduct() function, it's important to specify the customer to whom the product belongs. Currently, your code sets the customer name as an empty string (cus_name: "") without updating it when adding the product.

It's necessary to define the customer for whom the products are being added in order to properly track and manage them:

addProduct() {
  // Specify the customer name (e.g., "begueradj") when adding the product
  this.customer.cus_name = "begueradj"
  this.customer.cus_product.push({
    product_name: ""
  });
},

This code snippet is from your Vue component.

In the store's mutation logic, you need to first identify the customer with the specified name ("begueradj"). Depending on whether the customer already exists or not, two scenarios may arise:

  1. If the customer already exists, update their products list accordingly
  2. If the customer is new, add them to the customers list

In simpler terms, the following code snippet illustrates how this can be implemented:

const mutations = {
  addCustomer(state, customerData) {
     // Check if a customer with the given name already exists:
     const customer = state.customer.find(customer => customer.cus_name === customerData.cus_name)
     if (customer) {
       // If the customer exists, update their products list:  
       customer.cus_product.concat(customerData.cust_product)
     } else {
       // If the customer doesn't exist, add them to the customers list
       state.customer.push(customerData)
     }
  }
};

Answer №2

The issue at hand is not related to Vue or Vuex, but rather stems from the way Javascript handles arrays and Objects (non-primitive types) by reference instead of by value. This means that when passing these types as arguments, the original object or array is passed, not a copy - causing any changes made to the original to also affect the new one.

One potential solution is:

const mutations = {
    addCustomer(state, customerData) {
        const customerDataCopy = Object.assign({}, customerData);
        customerDataCopy.cus_product = [].concat(customerData.cus_product);
        state.customers.push(customerDataCopy);
    }
};

Alternatively, you can use a module like deep-copy npm package (which has 0 dependencies) to create a deep copy of non-primitive types and avoid such issues:

const dcopy = require('deep-copy');
const mutations = {
    addCustomer(state, customerData) {
        const customerDataCopy = dcopy(customerData);
        state.customers.push(customerDataCopy);
    }
};

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

Is there a way to adjust the pivot point of the object's rotation?

I have incorporated a 3D hamburger model on my website using Three.js. However, I am facing an issue where the rotation behaves unexpectedly. The burger is supposed to rotate around itself at a 45-degree angle, but instead, it rotates from the upper left c ...

Adding a fresh element and removing the initial item from a collection of Objects in JavaScript

I'm working on creating an array of objects that always has a length of five. I want to push five objects initially, and once the array reaches a length of five, I need to pop the first object and push a new object onto the same array. This process sh ...

Determine the coordinates of the visible portion of an overflowed (zoomed in) image on a mobile screen using HTML

Currently, I am developing a mobile application using HTML / JavaScript. In this application, users have the ability to pinch-in (zoom in) on an image to focus on a specific part. When zooming in, only a portion of the image is visible, not the entire imag ...

One opportunity to interact with the menu by clicking only once

I am encountering an issue with a menu div that starts off with opacity set to 0 and visibility hidden. The purpose is for this div to become visible when clicking on another div (a menu that sticks to the top of my page, toggle-able via click). Everythin ...

Efficiently Incorporating JavaScript Variables into DataTable's aoData

I am facing an issue with a variable named search_gen, which is generated through an ajax request (shown below). var search_gen; $.ajax({ type: "POST", url: link+module_name+'search_generator/'+module_active, dataType: "text", as ...

Material UI React Autocomplete Component

I'm currently working on integrating an Autocomplete component using the Material UI library. However, I've encountered a challenge - I'm unsure of how to properly pass the value and onChange functions, especially since I have a custom Text ...

Utilizing Angular to make API requests and handle promises

Currently, I am facing a challenge in my angular application which involves working with the soundcloud api. The issue arises when I make a call to the soundcloud api to retrieve my tracks, loop through them to extract the iframe embed object, inject it in ...

Tips for consuming a JSON object and generating two arrays in JavaScript

Is there a way to create two arrays from a JSON input, with one array containing only keys and the other containing only values, while excluding pairs where the key is numerically equal to the value? ...

Guide on utilizing ajax to post data when the URL parameter changes, all without refreshing the page

As the URL parameter changes, the values in my HTML also change. I am passing these values to a JSON file, but they are getting erased when the page refreshes due to the post request. I have attempted to use event.preventDefault(), however, it seems to n ...

What are the steps to set up ChartJS on a personal computer?

Currently, I am working on creating charts with ChartJS using the CDN version. However, I would like to have it installed directly on my website. After downloading ChartJS v4.1.1, I realized that it only contains typescript files. Since I cannot use TS fil ...

Ways to dynamically insert a new row into a table based on user input in a Postman-like reactive table

Is there a way to dynamically insert a row when a single character is entered into an input field in the header tab, similar to how Postman functions? 1) If a user types any single character in the td of the first row, then a new row should be added below ...

Is it possible to extract JSON data from a reverse geocoding request to Google

Looking to extract specific information from a reverse geocode response using Google Maps JavaScript API v3. geocoder.geocode({'latLng': latlng}, function(results, status) { if (status == google.maps.GeocoderStatus.OK) { ...

What is the best way to implement multilanguage support in nodejs without relying on cookies or external modules?

Currently, I am in the process of transitioning all my projects to node.js in order to enhance my JavaScript skills. Using Node.js along with the Express module, one of my clients who runs a translation company has requested that I incorporate two language ...

Angular Material is being improperly utilized by misusing the <label for=FORM_ELEMENT> tag

Encountering an issue with Angular Material while attempting to incorporate a <mat-label> element within a basic <mat-form-field>: https://i.sstatic.net/zQ4pp.png Below is the troublesome code snippet: <mat-form-field color="accent&qu ...

Is it possible to update the useContext value within a child component so that all other child components can access the updated value?

Is there a way to set a default value (like null) in a parent context and then change that value in a child component so other children can access the updated value? For example, imagine we have an App.jsx file where a userContext is created and passed do ...

When trying to find a substring within a string in JavaScript, the "else if" statement may not be triggered

I'm currently working on creating a Hangman game using HTML and JS. Most of the code is functioning properly, but I've hit a roadblock. For some reason, one part of my if else statement isn't working correctly. Here's the line of code: ...

Tips for retrieving a flag when there is a preexisting record within an association in Sequelize

I am working with a model A that has a 1:N association with a model B. My objective is to retrieve all records from A and determine whether there is at least one associated record from B (true) or not (false). The relationship setup: ModelA.hasMany(ModelB ...

When attempting to display a basic mesh in Three.js, the render does not showcase a simple cube as expected

My objective is to display a simple plane and a cube, however, the cube is being hidden by the plane. The position of the cube is between the camera and the plane, but for some reason, the plane appears to be blocking the view of the cube. This is how my ...

Is it possible to automate a query to an API through PHP and store the results on a local drive?

Recently, I created a webpage that fetches data from an API. However, the response time from the server is quite slow, taking around 10-20 seconds to retrieve the information. To mitigate cross-domain issues, I have set up a PHP proxy for the JavaScript re ...

AJAX success object encounters an uncaught type error

After successfully executing one of my AJAX Posts, there is a logical test with the returned "data" object. Surprisingly, upon page load, JavaScript throws an uncaught type error stating that it cannot read a property of undefined on this line: success: f ...