I have an LWC template like this:

<input list="counties">
<datalist id="counties">
  <template for:each={counties} for:item="county">
    <option key={county.Id}>{county.Name}</option>

I load the county records from the server. There are about 3,000 of them. When the counties are loaded and the template updates, it hangs the entire page for 10-20 seconds.

This is a fairly small amount of elements to insert into the DOM.

  1. Why are LWCs so slow when updating the DOM? What about them under the hood makes this such an inefficient operation?
  2. How can I speed this up, so that my autocomplete input can be populated by accurate information without hanging the entire page for 20 seconds?
  • 1
    Can you also share the update code from you js file? Commented Feb 3, 2021 at 3:53

1 Answer 1


It's not LWC, actually, but rather Locker Service that's causing the problem.

I created a pure LWC as a baseline without Locker Service interfering.

This runs in a fraction of a second, much less than 10 seconds or more; the page may take a second or two to compile the code, but the actual page execution is incredibly quick.

This has been a known issue since pretty much the beginning of Locker Service (API v40.0), such as this example.

You can avoid this problem by making sure the data isn't proxied. This can mean either copying the data beforehand (this.data = [...data]), or passing in a single JSON string and then parsing it in connectedCallback() or a setter method, depending on if you need reactivity (see example in the second link, above).

The "under the hood" problem is that the entire array has to pass through a filter callback every time you use an index operator, so 3,000 elements becomes at least 9,000,000 callbacks, which... well, you can see the result. Once you copy the data out so it's no longer caught in this filter trap, everything runs blazingly fast.

I've heard that salesforce.com is aware of the problem, but we don't yet have a timeline for a fix. Stay tuned.

  • If I loop over the array in an LWC method and manually create the option elements and manually append them to the DOM with appendchild, it is also almost instant. Is looping over the proxied data in an LWC method treated differently than doing it in the template?
    – Andy Ray
    Commented Feb 3, 2021 at 21:08
  • @AndyRay the problem is individual array accesses. A foeEach/map/ reduce/etc call only pays the filter penalty once. Merely cloning the data and assigning THAT to the variable that will be used in the template is sufficient. You don't need to render your own HTML or anything crazy. Just make a copy of the data that isn't boxed in.
    – sfdcfox
    Commented Feb 3, 2021 at 21:29

You must log in to answer this question.

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