Subscribe on changes!

$refs in slots disappear when wrapping Teleport

avatar
Sep 30th 2020

Version

3.0.0

Reproduction link

https://codesandbox.io/s/vue-ref-bug-dhsol?file=/src/App.vue

Steps to reproduce

follow the link image

What is expected?

$refs.ref2 & $refs.ref3 should be bind when focus the input.

What is actually happening?

they are undefined.

avatar
Sep 30th 2020

doesn't happen when using actual ref()s for the template refs:

https://codesandbox.io/s/vue-ref-bug-issue-2283-jrdvs

I assume it's caused in part by the slot optimizations - when App.vue re-renders, $refs is cleared:

https://github.com/vuejs/vue-next/blob/5d825f318f1c3467dd530e43b09040d9f8793cce/packages/runtime-core/src/renderer.ts#L1457

and all refs are updated in post-render Effects Queued up during the patch() phase by calling setRef():

https://github.com/vuejs/vue-next/blob/5d825f318f1c3467dd530e43b09040d9f8793cce/packages/runtime-core/src/renderer.ts#L551

But as the slot content sent to <lazy-teleport> doesn't need updating, so there's not vdom patching happening and so these refs are not added back to $refs again.

So the setRefs() method is called only once, for ref1 which is in the App.vue template.

Consequnetly, if we make the slot content depending on inputValue, it will update alongside App.vue and all 3 of the refs will be correctly set again each time.

Not sure this bug is limited to teleport. Also, not surte that the clearing of refs actually makes sense? When a vnode is unmounted, setRef will remove the ref anyways?

avatar
Sep 30th 2020

doesn't happen when using actual ref()s for the template refs:

https://codesandbox.io/s/vue-ref-bug-issue-2283-jrdvs

I assume it's caused in part by the slot optimizations - when App.vue re-renders, $refs is cleared and all refs are updated. but the slot content sent to <lazy-teleport> doesn't need updating, so there's not vdom patching happening and so these refs are not added back to $refs again.

This line:

https://github.com/vuejs/vue-next/blob/5d825f318f1c3467dd530e43b09040d9f8793cce/packages/runtime-core/src/renderer.ts#L551

is called 3 times when the lazy-teleport shows for the first time, but is only called once (for ref1) when App.vue updates.

Likewise, if we make the slot content depending on inputValue, it will update with App.vue and all3 of the refs will b e there each time.

Not sure this bug is limited to teleport.

Thanks! I wonder how do you debug code when there is an issue in vue itself. Create a soft link to vue-next repo build dist or by other methods?

avatar
Sep 30th 2020

in this case I looked up the section that updated refs in Vue's source and then set a breakpoint at that line in the devtool's sources tab.

avatar
Sep 30th 2020

in this case I looked up the section that updated refs in Vue's source and then set a breakpoint at that line in the devtool's sources tab.

Inside codesandbox?

avatar
Sep 30th 2020

yes, inside the fullscreen view that you can pop open.

avatar
Sep 30th 2020

yes, inside the fullscreen view that you can pop open.

Great, thanks.

avatar
Oct 2nd 2020

I just encountered this too. It seems to happen for every ref on elements inside of a child component's slot.