5

I have an array attribute in my LWC component which is set from the parent LWC. I have some logic that runs when the this attribute is set. I have used getter and setter for this. My array is a wrapper that has 3 attributes in it. There is a for loop in the setter that iterates over the array. When the size of the array is large say around 500, this loop processes very very slow. It takes a second per iteration or even more. This works perfectly fine when the array size is small. Even JSON.stringify(arr) takes 5 - 6 minutes if the array size is large. I tried to iterate the array in the parent component and it works fine there. I am not able to figure out what might be wrong.

@api
get optionsFromParent(){
    return this.options;
}
set optionsFromParent(opt){
    console.log('options are'+JSON.stringify(opt));
    for(let i=0;i<opt.length;i++){
           //do something here
    }
    this.options = opt;
}
11
  • if you add a console.log inside the loop, do you continuously see it being logged? Or does it start logging and then stop.
    – NSjonas
    Commented Jul 31, 2020 at 4:58
  • I checked by putting a log. The loop iterates very very slow. For just a console it is taking a second or even more per iteration. @NSjonas
    – Krish
    Commented Jul 31, 2020 at 5:03
  • So not really an infinite loop; just a really slow one. I've somehow managed to avoid writing LWC, so I can't offer much insight... Seems like there might be something else going on.
    – NSjonas
    Commented Jul 31, 2020 at 5:10
  • 1
    Might be you are updating that in renderedCallback, do you? Commented Jul 31, 2020 at 5:15
  • 1
    Running the chrome profiler might provide some insight: developers.google.com/web/tools/chrome-devtools/rendering-tools Otherwise, I'd recommend creating a minimal reproducible example
    – NSjonas
    Commented Jul 31, 2020 at 5:16

1 Answer 1

8

On the assumption this is this performance issue, this is effectively a bug in the LWC infrastructure. The workaround is to ensure each component accepts the array in an API property with a setter and ensure that you forcibly unproxy the data. Something like the following (this will copy all relevant properties from the options regardless of what they are called):

_options;

@api get options() {
    return this._options;
}

set options(value) {
    this._options = value.map(option => Object.assign({}, option));
}

The setter method explicitly removes any proxying by generating a new array with new objects in it that are the same structure as the inputs.

If you do this at the parent and child levels you should find the performance is improved.

2
  • Thanks @PhilW. I will try this solution.
    – Krish
    Commented Jul 31, 2020 at 7:27
  • 1
    This worked great! My component was timing out before, now it loads really fast
    – mike537
    Commented Nov 30, 2022 at 18:38

You must log in to answer this question.

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