vue icon indicating copy to clipboard operation
vue copied to clipboard

Error thrown when using transition-group with conditionally rendered children

Open riophae opened this issue 5 years ago • 13 comments

Version

2.5.16

Reproduction link

https://codepen.io/riophae/pen/EpgWdZ

Steps to reproduce

  1. Open the pen and it shows 1, 3, 5
  2. 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)

riophae avatar Jul 18 '18 19:07 riophae

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 avatar Jul 19 '18 07:07 maxirozay

@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.

riophae avatar Jul 19 '18 08:07 riophae

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.

maxirozay avatar Jul 19 '18 09:07 maxirozay

what is c$1.elm.getBoundingClientRect is not a function? Did you fix?

shinriyo avatar Nov 29 '18 14:11 shinriyo

@shinriyo See: https://github.com/vuejs/vue/blob/504d5da7eff1c77117c2f57b0c4238e56de80fc5/src/platforms/web/runtime/components/transition-group.js#L80

riophae avatar Dec 03 '18 07:12 riophae

Any update?

Daiver13 avatar Oct 31 '19 13:10 Daiver13

i have the same issue

kostia7alania avatar Oct 31 '19 14:10 kostia7alania

I am having the same issue but with v-show on 2.6.10

selfagency avatar Nov 12 '19 08:11 selfagency

@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

  1. Open a new issue
  2. Provide runnable code that demonstrates the problem.

Otherwise you will likely not get helpful feedback.

LinusBorg avatar Nov 12 '19 09:11 LinusBorg

@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.

selfagency avatar Nov 12 '19 17:11 selfagency

PR which would fix this issue: #11128

yannisgu avatar Apr 16 '20 08:04 yannisgu

For me, I just wrapped my custom elements with divs and applied the v-if statements on those divs

Abdulrahmanh995 avatar Oct 07 '21 06:10 Abdulrahmanh995

Make sure all child elements have a unique key attribute. Also be careful if you are rendering fragments inside.

badalya1 avatar Aug 30 '22 16:08 badalya1