lwc
lwc copied to clipboard
if-elseif-else used inside an iteration doesn't benefit from keys
Description
When we use the if-elseif-else directives as a direct child of an iteration, we're unable to benefit from any optimization using the keys due to how the nodes are generated.
If we use the directives as part of a template, the top level nodes in the list use the key of the if-elseif-else fragments, rather than the key of the actual content. It's not possible for the user to provide a key for a template node, so there's no way around this.
If we use the directives inline in an element or component, the user can provide a key for the node, but the top level nodes in the list are still the if-elseif-else fragments and their keys. The keys provided by the user are attached to the element or custom element nodes, which are children of the conditional directive nodes.
Example
Right now,
<template for:each={items} for:item="item">
<div lwc:if={item.visible} key={item.key}>{item.value}</div>
</template>
gets compiled as something like
return api_iterator($cmp.items, function (item) {
return item.visible
? api_fragment(
0,
[
api_element(
"div",
{
key: api_key(1, item.key),
},
[item.value]
),
],
0
)
: null;
});
The user-provided key is not available for the diffing algo when patching the list.
Expected Results
We should look into how we might optimize the use of if-elseif-else as the top level child in an iteration.
Constant Conditional in Iteration
If a constant or some condition unrelated to the values being iterated through is used, this is an issue with best practices:
<template for:each={items} for:item="item">
<template lwc:if={visible}>
<div key={item.key}>Conditional Iteration</div>
</template>
</template>
can and probably should be written as:
<template lwc:if={visible}>
<template for:each={items} for:item="item">
<div key={item.key}>Conditional Iteration</div>
</template>
</template>
No different from general programming:
for(let i=0; i<items.length; i++) {
if(visible) { ... };
}
versus
if (visible) {
for(let i=0; i<items.length; i++) {
...
}
}
Actual Results
Browsers Affected
Version
- LWC: x.x.x
Possible Solution
Additional context/Screenshots See https://github.com/salesforce/lwc/pull/3030#discussion_r983880586 for more details on the context