5

Imagine we have a parent component where we create an array like so:

@track stuff = [];

connectedCallback() {
     let newArray = [];

     for (let s = 0; s < 10000; s++) {
          newArray.push({ prop1: 'One' + s, prop2: 'Two' + s, prop3: s, prop4: [s] });
     }

     this.stuff = [...newArray];
}

On my system this takes some 5 ms.

now I pass this array to my child component:

<c-child-component stuff={stuff}></c-child-component>

And in my child component I have a button

<lightning-button label="click me" onclick={handleClick}></lightning-button>
@api stuff; 

handleClick() {
     let newItems = [];

     for (let s = 0; s < this.stuff.length; s++) {
          if (this.stuff[s]['prop3'] % 2 == 0) {
               newItems.push(this.stuff[s]);
          }
     }
}

This handleClick method takes a whopping 130 seconds on my system, simply iterating through the array.

What is actually happening is aura_prod.js is locking every property on every element in an array and so has to decide if that property is reactive or not. This is painfully slow and basically makes this unusable.

What is the recommended approach for this?

7

Use Array methods instead, for this causes the Locker Service security filter method to apply only once. Note that this is a Locker Service problem, not a LWC problem. If you use LWC OSS, you'll find your code would perform perfectly well (as I'll demonstrate below).

@api stuff; 

handleClick() {
  let newItems = this.stuff.filter(item => (item.prop3 % 2 == 0));
}

I wrote a demo for you. It takes about 18ms for my computer to calculate the new list using my code, 19ms for yours (time may vary a bit, but should be <50ms). But with Locker Service, you should notice probably 20-30ms for my code, and minutes for yours. This is normal, and expected.

You must not access individual elements of an @api marked variable. Always use either Array.prototype methods, or clone the list first with let localCopy = [...stuff]; and work on that, instead.

This happens because, for an individual array access, the Locker Service filter has to filter all 10,000 items. So, iterating 10,000 times over 10,000 elements, means a total of 100,000,000 array accesses. Oops.

4
  • Thank you! this helped heaps because i was almost resigned to resorting to something like JSON.stringify() in parent and then JSON.parse() in child. – zaitsman May 11 at 1:17
  • 1
    @zaitsman That's technically possible, but rather an annoying workaround. Using a copy in the child is actually the ideal scenario. – sfdcfox May 11 at 2:19
  • @sfdcfox since it's locker service not LWC, is the same behaviour observable in Aura? Would you know? – Christian Szandor Knapp May 11 at 6:07
  • @ChristianSzandorKnapp Yes, Aura does have the same issue, and the same workarounds are suggested. – sfdcfox May 11 at 12:03
4

I had experienced the same a while back, and learned that this is a limitation with locker service as mentioned by @sfdcfox.

You can find the explanation is documented as well:

Arrays Proxied When Passed to Child Components

A page that’s using a component that passes a large array of objects through layers of child components can become unresponsive

recommendations by Salesforce are narrowed down to:

  • Avoid passing large arrays of objects more than one level down. For example, pass an array from parent to child but no further.
  • Divide your data into multiple smaller arrays in the parent component.

personally, I avoid passing large sets of data in between components due to this limitation. Hopefully SF will come up with something...

2
  • 3
    +1 Glad to see that's been acknowledged as a limitation in the documentation, didn't know they added that. – sfdcfox May 11 at 1:06
  • @glls Yeah this is definitely extremely annoying and unfortunately due to the design of my code it's almost inevitable that i need to pass something like hundreds of thousands of rows centrally fetched in parent component to multiple sub components. – zaitsman May 11 at 1:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.