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

Duplicate key for transition group fragment when child has v-if #5761

Open
bodograumann opened this issue Apr 20, 2022 · 8 comments · May be fixed by #5779
Open

Duplicate key for transition group fragment when child has v-if #5761

bodograumann opened this issue Apr 20, 2022 · 8 comments · May be fixed by #5779
Labels
has workaround A workaround has been found to avoid the problem 🐞 bug Something isn't working 🔩 p2-edge-case scope: transition

Comments

@bodograumann
Copy link

Version

3.2.33

Reproduction link

sfc.vuejs.org/

Steps to reproduce

Have a <template v-for> inside a <TransitionGroup>, with multiple children and one of those children has v-if. For example:

<template>
  <TransitionGroup>
    <template v-for="(item, idx) of ['A', 'B']" :key="item">
      <div>{{ idx }}: {{ item }}1</div>
      <div v-if="idx < 1">{{ idx }}: {{ item }}2</div>
    </template>
  </TransitionGroup>
</template>

What is expected?

Here the keys should be A0, A1 and B0.

What is actually happening?

But instead we get A0, A0 and B0.


Without the v-if everything works correctly and we get A0, A1, B0 and B1.

In the reproduction I have used a component for the children, so the generated key is easily visible in the devtools.

Related commit: 4311ddd
Related issues: #4718, #5360, #5392

@bodograumann
Copy link
Author

Not completely sure what you want to say, @coder-hxl .
The visible output is fine, but the key attributes contain duplicates.
You need to use the devtools to look at them.

@edison1105 edison1105 added 🐞 bug Something isn't working scope: transition labels Apr 21, 2022
@edison1105
Copy link
Member

edison1105 commented Apr 21, 2022

should be a bug.
this is because v-if with a default key.
image

@bodograumann
Copy link
Author

I don’t know how the key calculation for the v-if works, but maybe it would be good to allow defining the child keys manually, instead of using the index here.
Afaics the code can handle it in theory, but when I try to define the key on the parent template element as well as on each child, I get a compiler error:
SyntaxError: <template v-for> key should be placed on the <template> tag.

@yuwu9145
Copy link
Contributor

yuwu9145 commented Apr 22, 2022

I guess we need to clarify expect behaviour first, is it supposed to be: ??

<TransitionGroup>
    <template v-for="(item, idx) of ['A', 'B']" :key="item">
      <Item>{{ idx }}: {{ item }}1</Item> // key: B0
      <Item>{{ idx }}: {{ item }}2</Item> // key: B1
      <Item v-if="idx < 1">{{ idx }}: {{ item }}3</Item>  // key: B2
      <template v-else><Item>no<Item></template>  // key: should here be B2 or B3 ?
      <Item>{{ idx }}: {{ item }}4</Item>   // key: should here be B3 or B4 ?
      <Item>{{ idx }}: {{ item }}5</Item>   // ....
    </template>
  </TransitionGroup>

My pull request 5779 results in following result:

<TransitionGroup>
    <template v-for="(item, idx) of ['A', 'B']" :key="item">
      <Item>{{ idx }}: {{ item }}1</Item> // key: B0
      <Item>{{ idx }}: {{ item }}2</Item> // key: B1
      <Item v-if="idx < 1">{{ idx }}: {{ item }}3</Item>  // key: B2 (if this branch is valid)
      <template v-else><Item>no<Item></template>  // key:  B2
      <Item>{{ idx }}: {{ item }}4</Item>   // key: B3
      <Item>{{ idx }}: {{ item }}5</Item>   // key: B4
    </template>
  </TransitionGroup>

It completely re-calculates keys based on index position in the list and ignores number type keys from v-if node.

@bodograumann
Copy link
Author

Off the top of my head I would say your solution sounds perfectly reasonable.
I expect, however, that the user’s expectation might be different depending on the situation.
That’s why I suggested allowing explicit keys for all raw children.

@iwusong
Copy link
Contributor

iwusong commented Apr 26, 2022

children component with v-if can be seted explicit key no warn

@bodograumann
Copy link
Author

Ah, thank you for the tip, @iwusong. Setting a key on the v-if items is a good workaround.

@yuwu9145
Copy link
Contributor

yuwu9145 commented Apr 26, 2022

explicit key on child v-if node is nice workaround, just need to be aware that a custom key of "number type" on v-if could still be duplicated with other default index key because the fundamental issue is caused by "number type keys on v-if node".

So using types other than number should be good enough 👍

@sodatea sodatea added has workaround A workaround has been found to avoid the problem 🔩 p2-edge-case labels Mar 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has workaround A workaround has been found to avoid the problem 🐞 bug Something isn't working 🔩 p2-edge-case scope: transition
Projects
None yet
5 participants