3

I am fetching data from apex class in a local map variable in LWC javascript.Even after using @track my output is getting duplicated.As in, opn calling the methods the old data is not replaced with new ones's.Another set of new data is getting added under the old data.

import getGroups from '@salesforce/apex/LC_onBoardingController.getGroups';

@track mapOfGroups = [];
 handleLoadGroups() {
        getGroups()
            .then(result => {
                if (result) {
                    for (let key in result) {

                        if (result.hasOwnProperty(key)) {
                            this.mapOfGroups.push({ value: result[key], key: key });
                            console.log("groupsmap***"+JSON.stringify(this.mapOfGroups));
                        }
                    }
                }

            })
            .catch(error => {
                window.console.log("groupsmap***error");

            });
    }

On click of a button i am calling a method say

backtoGroups(event) {

        this.handleLoadGroups();

        this.UserStage = "GROUPS";

    }

So the new data is coming but its getting appended to the old one instead of getting replaced. Is there something I am missing or doing mistake in?

1
  • Don't you want to just truncate your "mapOfGroups" array (it is not a map) at the start of your "then" handler function? I.e. mapOfGroups = [];
    – Phil W
    Commented Feb 14, 2020 at 11:44

2 Answers 2

3

I would solve this with one of the JS array functions that is purpose built for this. In this instance, Array.prototype.map().

As stated in the docs, the map() function always creates a new array, meaning that a call to it will have you from having to manually clear the map.

There is also a practice that seems to be developing in JS these days to try to use patterns that follow functional programming practices, in this instance, not mutating variables in place. I'll leave it to you decide for yourself whether or not this is important.

Here's a simple example:

const array1 = [1, 2, 3];

let array2 = array1.map(item => `Number ${item}`)

With that in mind (and as of Spring 20 when all properties cease to require @track provided they are not mutated in place), you could do this:

mapOfGroups = [];

handleLoadGroups() {
  getGroups()
    .then( result => {
      if (result) {
        this.mapOfGroups = Object.keys(result).map( key => {key: key, value: result[key]});
      }
      ...

(Or something like that...I'm doing this without actually running this code myself, so there may be a slight typo or something.)

In any case, there are a bunch of higher order functions for JS Array, that are super useful (even if you don't really care about the whole functional-immutability-is-cool thing) and they're awesome, and they're there to help you out.

Just take care on browser support is all. A quick search on caniuse.com can spare you a big headache when that user comes along and accesses your component on an old version of Edge or Opera some such.

2

Update your code along these lines:

@track mapOfGroups = [];
handleLoadGroups() {
    getGroups()
        .then(result => {
            if (result) {
                this.mapOfGroups = []; // Clear previous values

                Object.keys(result).forEach(key => {
                    this.mapOfGroups.push({ key: key, value: result[key] });
                });
            }
            ...

To minimize rerendering you might actually do:

@track mapOfGroups = [];
handleLoadGroups() {
    getGroups()
        .then(result => {
            if (result) {
                let groups = []; // Clear previous values

                Object.keys(result).forEach(key => {
                    groups.push({ key: key, value: result[key] });
                });

                this.mapOfGroups = groups;
            }
            ...

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .