vue
vue copied to clipboard
Error thrown when using transition-group with conditionally rendered children
Version
2.5.16
Reproduction link
https://codepen.io/riophae/pen/EpgWdZ
Steps to reproduce
- Open the pen and it shows 1, 3, 5
- Click the button
What is expected?
It should show 3, 5
What is actually happening?
Got this error in console:
[Vue warn]: Error in render: "TypeError: c$1.elm.getBoundingClientRect is not a function"
found in
---> <TransitionGroup>
<Root>
TypeError: c$1.elm.getBoundingClientRect is not a function
at Proxy.render (VM643 vue.js:8383)
at VueComponent.Vue._render (VM643 vue.js:4535)
at VueComponent.updateComponent (VM643 vue.js:2788)
at Watcher.get (VM643 vue.js:3140)
at Watcher.run (VM643 vue.js:3217)
at flushSchedulerQueue (VM643 vue.js:2981)
at Array.<anonymous> (VM643 vue.js:1839)
at MessagePort.flushCallbacks (VM643 vue.js:1760)
The transition try to modify an element from the v-for that is not rendered because of the v-if. You can use v-show instead of v-if to render the element. The best solution for me would be to filter the list in a computed property and give the filtered list in your v-for.
@maxirozay Hi Maxime, thanks for your reply.
My actual use case is that, I was not rendering a list inside <transition-group />
, but some different components . And I was not using template but JSX. So there is no v-if
or v-show
. I was conditionally rendering the children using if
statement in the child component's render function. When I didn't want to show the compent, I returned null
in its return function. So I should try change that to set display: none
.
But I still think it would be better for Vue to be able to handle cases like mine, since my code is very normal and not doing anything wrong :) Anyway, with display: none
it should work.
You're welcome Fangzhou.
display: none
should work. But if you still have a v-for
with a list the best solution is still to filter the list then give the filtered list to your v-for
. Then in your JSX component you only care about rendering the component and never return null.
Yes that is weird that transition-group is trying to transition something that doesn't exist but it can be easily avoided. Maybe somebody who knows more about that can look at it.
what is c$1.elm.getBoundingClientRect is not a function
?
Did you fix?
@shinriyo See: https://github.com/vuejs/vue/blob/504d5da7eff1c77117c2f57b0c4238e56de80fc5/src/platforms/web/runtime/components/transition-group.js#L80
Any update?
i have the same issue
I am having the same issue but with v-show
on 2.6.10
@selfagency This issue is almost 1.5 years old and using v-show was established as a workaround.
So if you have the same issue now, 1.5 years later, but with v-show, it might be a good idea to
- Open a new issue
- Provide runnable code that demonstrates the problem.
Otherwise you will likely not get helpful feedback.
@LinusBorg I figured out my issue—
In my component, I was trying to alternate between two global components using v-show
. My guess was that the subcomponent needed to render before trying to attach an event to it, and there was a race condition preventing it from doing so. So, I wrapped the global components in div
tags and put the v-show
on those, and then my problem was solved. Could this possibly also be resolved by using an async component?
Before (throws error)
<transition-group name="zoom" mode="out-in">
<inline-svg v-show="modal" key="close" :src="close" width="25" height="25"></inline-svg>
<inline-svg v-show="!modal" key="open" :src="open" width="25" height="25"></inline-svg>
</transition-group>
After (no error)
<transition-group name="zoom" mode="out-in">
<div v-show="modal" key="close">
<inline-svg :src="close" width="25" height="25"></inline-svg>
</div>
<div v-show="!modal" key="open">
<inline-svg :src="open" width="25" height="25"></inline-svg>
</div>
</transition-group>
I hope this helps others.
PR which would fix this issue: #11128
For me, I just wrapped my custom elements with div
s and applied the v-if
statements on those div
s
Make sure all child elements have a unique key
attribute. Also be careful if you are rendering fragments inside.