Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

for:each within for:each without explicit key can lead to vdom errors #4889

Open
nolanlawson opened this issue Nov 18, 2024 · 3 comments
Open
Labels

Comments

@nolanlawson
Copy link
Contributor

nolanlawson commented Nov 18, 2024

(Salesforce Known Issue)

If you have an iteration (for:each) within another iteration:

<template>
    <template for:each={children} for:item="child">
        <x-row lwc:if={child.renderMe} prop={child} key={child.id}></x-row>
        <template lwc:if={child.children} for:each={child.children} for:item="grandchild">
            <x-row lwc:if={grandchild.renderMe} prop={grandchild} key={grandchild.id}></x-row>
        </template>
    </template>
</template>

... and if you have a sufficient number of lwc:if layers and duplicated keys between the grandchildren and the children, then you can get a runtime error:

TypeError: Cannot use 'in' operator to search for 'prop' in undefined

Thrown by:

Or:

TypeError: Failed to execute 'removeChild' on 'Node': parameter 1 is not of type 'Node'.

Thrown by:

const removedNode = removeChild.call(this, oldChild);

One workaround is to put a key around the inner loop:

 <template>
     <template for:each={children} for:item="child">
         <x-row lwc:if={child.renderMe} prop={child} key={child.id}></x-row>
+        <div key={child.id}>
         <template lwc:if={child.children} for:each={child.children} for:item="grandchild">
             <x-row lwc:if={grandchild.renderMe} prop={grandchild} key={grandchild.id}></x-row>
         </template>
+        </div>
     </template>
 </template>

Another workaround is to flatten the array. E.g.:

get flattenedArray() {
  return this.children.map(child => [child, ...child.children]).flat() // something like this
}

... and then use a single for:each:

<template for:each={flattenedArray} for:item="child">
    <!-- ... --->
</template>

Repro for first error: nolanlawson/lwc-barebone@836362a
Repro for second error: nolanlawson/lwc-barebone@a97223c

Repro steps: pnpm i && pnpm run dev

Copy link

git2gus bot commented Nov 18, 2024

This issue has been linked to a new work item: W-17266520

@nolanlawson nolanlawson added the vdom Virtual DOM label Nov 19, 2024
@nolanlawson
Copy link
Contributor Author

Potential fix: we could use a VFragment for for:each. This may help the vdom diffing to distinguish between different for:each blocks.

@nolanlawson
Copy link
Contributor Author

Interestingly, my attempt to use a VFragment did not resolve the issue, and caused 4 other test failures in the Karma tests.

The issue here seems to be that we land in this code path but the elm on both the n1 and n2 are undefined:

// Otherwise patch the existing component with new props/attrs/etc.
const elm = (n2.elm = n1.elm!);
const vm = (n2.vm = n1.vm);

nolanlawson added a commit that referenced this issue Dec 18, 2024
nolanlawson added a commit that referenced this issue Dec 18, 2024
nolanlawson added a commit that referenced this issue Dec 18, 2024
wjhsf added a commit that referenced this issue Dec 20, 2024
* test(ssr): add tests for nested elements in slots (#5048)

* fix(compiler): log warning for missing name/namespace (#4825)

* test(karma): remove unnecessary IE11-related code (#5054)

* fix: replace barrel exports from `lwc` with `@lwc/ssr-runtime` (#5034)

* fix: replace barrel from `lwc` package with '@lwc/ssr-runtime'

* fix: handle * barrel case and corresponding tests

* fix: function naming

* fix: barrel import test parity

* fix: include optional exported alias for export all declaration replacement, tests

* chore: explain function name massaging in test

* fix: deep clone objects and optimize tests

* fix: remove unused shared file

* test(karma): add test for for:each issue #4889 (#5053)

* fix(ssr): missing bookends for slotted lwc:if not at the top-level (#5027)

Co-authored-by: Nolan Lawson <[email protected]>

* fix(ssr): fix HTML comment bookends for if blocks (#5055)

Co-authored-by: Will Harney <[email protected]>

* fix(ssr-compiler): namespace and name should be optional in ComponentTransformOptions (#5058)

* test(ssr): test `if` with adjacent text (#5056)

* test(karma): reduce #4889 even further (#5060)

* fix(ssr): fix `style` attribute rendering (#5061)

* fix(ssr-compiler): harmonize some wire errors (#5062)

Co-authored-by: Will Harney <[email protected]>

* fix: only call callback when needed @W-17420330 (#5064)

* fix: only call callback when needed @W-17420330

* chore: simplify test

* fix: use correct class check

* fix(ssr): render from superclass (#5063)

Co-authored-by: Nolan Lawson <[email protected]>

* test(ssr): add more superclass tests (#5065)

* fix: use correct shadow root @W-17441501 (#5070)

* fix: use correct shadow root @W-17441501

* chore: yagni i guess

* chore: 🛩️📦

* If you read this, tell me so!

* fix(ssr): align csr and ssr reflective behavior (#5050)

* chore: release v8.12.2 @W-17485572 (#5075)

---------

Co-authored-by: Nolan Lawson <[email protected]>
Co-authored-by: jhefferman-sfdc <[email protected]>
Co-authored-by: Matheus Cardoso <[email protected]>
Co-authored-by: Nolan Lawson <[email protected]>
Co-authored-by: Eugene Kashida <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant