vuejs/core

Static Slots optimization combined with component instance re-use can lead to stale slot content never being updated. [EDGE CASE]

Jokcy opened this issue · 4 comments

Jokcy commented

Version

3.0.4

Reproduction link

https://codesandbox.io/s/demo-for-sfc-slots-issue-n27kc

Steps to reproduce

You can see Hello never change to World.

I already find the reason is that SFC compiler add { _: 1 } to the compiled slots, which in updateSlots tell Vue there is no need to update instance.slots. But in this case, it work not correctly.

What is expected?

Hello and World switch in 1 second

What is actually happening?

never update

The cause is that the slots for each <A> are indeed stable and don't need updating, but Vue is re-using the same instance of A for efficiency when you toggle between the two vnodes.

Not sure we can fix this at the compiler level without de-optimizing the usually justified use-cases of keeping slots stable.

It can be corrected by applying a key to each instance of A:

<template>
  <B>
    <A key="A">Hello</A>
    <A key="B">World</A>
  </B>
</template>

You could also apply these keys to the vnodes within the render function of B, depending on your use case.

Jokcy commented

The cause is that the slots for each <A> are indeed stable and don't need updating, but Vue is re-using the same instance of A for efficiency when you toggle between the two vnodes.

Not sure we can fix this at the compiler level without de-optimizing the usually justified use-cases of keeping slots stable.

It can be corrected by applying a key to each instance of A:

<template>
  <B>
    <A key="A">Hello</A>
    <A key="B">World</A>
  </B>
</template>

You could also apply these keys to the vnodes within the render function of B, depending on your use case.

Yeah I know key will help to fix this. But I guess it's better to update this behavior because I spend 2-3 hours to find out why😂, it's really confusing when I face it.

Well I'm saying that at least I personally don't see how, as the problem you are facing here is not detectable by static analysis during compilation.

So the only way I can see would be to never optimize slots in this way, which is too high a price to solve such an edge case, in my opinion.

Maybe a better route would be to document the edge cases one can come across when manually manipulating slots content in render functions.

Jokcy commented

Yeah, if only edge case like this will face this issue, maybe a doc is enough. Can we find a way to warning when people manually manipulating slots content in render functions?