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

TransitionGroup getBoundingClientRect is not a function #6745

Closed
yurirnascimento opened this issue Sep 24, 2022 · 11 comments
Closed

TransitionGroup getBoundingClientRect is not a function #6745

yurirnascimento opened this issue Sep 24, 2022 · 11 comments
Labels
has PR A pull request has already been submitted to solve the issue scope: transition

Comments

@yurirnascimento
Copy link

Vue version

3.2.31

Link to minimal reproduction

https://stackblitz.com/edit/vitejs-vite-srxkag?file=src%2Fcomponents%2FHelloWorld.vue

Steps to reproduce

In parent component I have

<TransitionGroup appear>
    <template v-for="item in list" :key="item.id">
      <Notification
        v-if="item.visible"
        :notification="item"
        @close="handleClose"
      />
    </template>
</TransitionGroup>

And if child component init with html comment

<template>
  <!-- COMMENT -->
  <div>
    {{ notification.title }} -
    <button type="button" @click="handleClose">Clickme</button>
  </div>
</template>

I get the "TypeError: child.el.getBoundingClientRect is not a function"

Work if I remove the HTML comment from first line in template.

What is expected?

Execute the transition correctly, with or without comment on the child element

What is actually happening?

TypeError: child.el.getBoundingClientRect is not a function

System Info

No response

Any additional comments?

No response

@jonaskuske
Copy link
Contributor

jonaskuske commented Sep 26, 2022

There are two issues at play here:

  1. Components used in <TransitionGroup> break if they don't have a single-element root but render a Fragment (multiple root nodes). This is currently not documented for <TransitionGroup>, only for <Transition>:

    image

    Also, the warning that's printed if you use a multi-root component in a <TransitionGroup> only mentions <Transition>:

    if (__DEV__ && !isElementRoot(root)) {
      warn(
        `Component inside <Transition> renders non-element root node ` +
          `that cannot be animated.`
      )
    }

    In Vue 2, <TransitionGroup> did support multi-root (functional) components as children, so this is either a bug or a non-documented breaking change!

  2. The behavior of components that have multiple root nodes (includes comments) but only one root element is inconsistent between dev & prod:

    • In production, comments are usually stripped during compilation, so components render a single root element instead of a fragment. This is why your example does actually work in production mode (vite build / vite preview), it only breaks in development mode.
    • In development, comments are not stripped, so components render fragments, breaking <TransitionGroup>. However, Vue pretends that the component is single-root during checks, because it knows that this will be the case once you build for production. That's why isElementRoot() returns true in the above warning check and the warning is not logged, despite the component actually not having an element root but rendering a fragment and breaking the transition.

@ssche
Copy link

ssche commented Oct 28, 2022

Another use case arises when using custom components within a <transition-group> as a grid layout (display: grid). The elements need to be rendered as individual elements without a common root, so the grid layout works as expected.

@locki13freja
Copy link

locki13freja commented Jan 28, 2023

`


Post list

	<TransitionGroup name="post-list">
		<PostItem
			v-for="post in posts"
			:post="post"
			:key="post.id"
			@remove="$emit('remove', post)"
		/>
	</TransitionGroup>
</div>
<h2 v-else style="color: red">Post list empty</h2>
` error:Uncaught (in promise) TypeError: child.el.getBoundingClientRect is not a function !

Why this not working?

@jonaskuske
Copy link
Contributor

@locki13freja What does the template of PostItem look like?

@kudp02
Copy link

kudp02 commented Mar 17, 2023

I fixed this error by removing a comment in a child component just above the </template>

@tsboh
Copy link

tsboh commented Jul 29, 2023

I fixed this error by changing the place of the v-if

The transition worked when 'isOpen' became true. The error occurred when 'isOpen' became false.

After changing the place of the v-if from:

<TransitionGroup name="pos-items-list"
	enter-active-class="transition duration-100 ease-out"
	enter-from-class="transform scale-95 opacity-0"
	enter-to-class="transform scale-100 opacity-100"
	leave-active-class="transition duration-75 ease-out"
	leave-from-class="transform scale-100 opacity-100"
	leave-to-class="transform scale-95 opacity-0"
> 
                            <template v-if="isOpen" v-for="(posItem,key) in posItems" :key="Math.random()">
                                      <ShowItemCard v-if="posItem.products.length > 1"  :key="posItem.id + 'levelflex'" />
                                      <ShowItem     v-else                              :key="posItem.id + 'level'"     />
                                        
                            </template>
</TransitionGroup>

to so:

<template v-if="isOpen" v-for="(posItem,key) in posItems" :key="Math.random()">
                            <TransitionGroup name="pos-items-list"
                              enter-active-class="transition duration-100 ease-out"
                              enter-from-class="transform scale-95 opacity-0"
                              enter-to-class="transform scale-100 opacity-100"
                              leave-active-class="transition duration-75 ease-out"
                              leave-from-class="transform scale-100 opacity-100"
                              leave-to-class="transform scale-95 opacity-0"
                            > 
                                      <ShowItemCard v-if="posItem.products.length > 1"  :key="posItem.id + 'levelflex'" />
                                      <ShowItem     v-else                              :key="posItem.id + 'level'"     />
                                        
                           </TransitionGroup>
 </template>

It all worked. Seems logical: It was trying to transition an emtpy/non-existing 'element'.

@yurirnascimento [v-if="item.visible"] and @locki13freja: could that have been the problem in your case too?
Anyway just to find common ground. Happy coding

@haoqunjiang haoqunjiang added the has PR A pull request has already been submitted to solve the issue label Aug 29, 2023
@yassernasc
Copy link

In my case, I solved this by changing from:

<TransitionGroup name="list" tag="div">
    <CustomComponent v-for="item in items" :key="item.id" :componentProp="prop" />
</CustomComponent>

To:

<TransitionGroup name="list" tag="ul">
  <li v-for="item in items" :key="item.id">
    <CustomComponent :componentProp="prop" />
  </li>
</TransitionGroup>

@Tobiaqs
Copy link

Tobiaqs commented Sep 13, 2023

It seems I am no longer encountering this issue in Vue 3.3.4

@VladBrok
Copy link

VladBrok commented Jan 7, 2024

There are two issues at play here:

  1. Components used in <TransitionGroup> break if they don't have a single-element root but render a Fragment (multiple root nodes). This is currently not documented for <TransitionGroup>, only for <Transition>:
    image
    Also, the warning that's printed if you use a multi-root component in a <TransitionGroup> only mentions <Transition>:

    if (__DEV__ && !isElementRoot(root)) {
      warn(
        `Component inside <Transition> renders non-element root node ` +
          `that cannot be animated.`
      )
    }

    In Vue 2, <TransitionGroup> did support multi-root (functional) components as children, so this is either a bug or a non-documented breaking change!

  2. The behavior of components that have multiple root nodes (includes comments) but only one root element is inconsistent between dev & prod:

    • In production, comments are usually stripped during compilation, so components render a single root element instead of a fragment. This is why your example does actually work in production mode (vite build / vite preview), it only breaks in development mode.
    • In development, comments are not stripped, so components render fragments, breaking <TransitionGroup>. However, Vue pretends that the component is single-root during checks, because it knows that this will be the case once you build for production. That's why isElementRoot() returns true in the above warning check and the warning is not logged, despite the component actually not having an element root but rendering a fragment and breaking the transition.

@Tobiaqs thank you, I had this bug because I had multiple root notes, but one of them was just a comment and I didn't thought that it may cause the issue, but it did

@Tobiaqs
Copy link

Tobiaqs commented Feb 28, 2024

It seems I'm still encountering this issue, even in Vue 3.4.x

This is my workaround (works with Vite). It disables transitions in dev. In prod everything works...

// FixedTransitionGroup.vue
//
// Usage:
// <FixedTransitionGroup
//    enter-active-class="transform ease-out duration-300 transition"
//    enter-from-class="translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-2"
//    enter-to-class="translate-y-0 opacity-100 sm:translate-x-0"
//    leave-active-class="transition ease-in duration-100"
//    leave-from-class="opacity-100"
//    leave-to-class="opacity-0">
//        <!-- your content -->
// </FixedTransitionGroup>

<template>
    <TransitionGroup v-if="PROD" v-bind="$attrs">
        <slot></slot>
    </TransitionGroup>
    <template v-else>
        <slot></slot>
    </template>
</template>

<script lang="ts" setup>
defineOptions({
    inheritAttrs: false,
})

const PROD = import.meta.env.PROD
</script>

jonaskuske added a commit to jonaskuske/core that referenced this issue Mar 1, 2024
jonaskuske added a commit to jonaskuske/core that referenced this issue Mar 1, 2024
@edison1105
Copy link
Member

Closing as it had been fixed via #9421

@edison1105 edison1105 closed this as not planned Won't fix, can't repro, duplicate, stale Sep 3, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Sep 19, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
has PR A pull request has already been submitted to solve the issue scope: transition
Projects
None yet
Development

Successfully merging a pull request may close this issue.