Vue: Error thrown when using transition-group with component v-bind:is directive

Created on 6 Jul 2018  路  3Comments  路  Source: vuejs/vue

Version

2.5.16

Reproduction link

https://jsfiddle.net/50wL7mdz/451168/

Steps to reproduce

Render a component (not just any component, but the build-in one: https://vuejs.org/v2/api/#component), with the v-bind:is directive set to "transition-group" (or simply is="transition-group"):

<component is="transition-group"></component>

What is expected?

I expect no errors to be thrown.

What is actually happening?

This component appears to work as expected but throws the following error in the console:

vue.js:597 [Vue warn]: Unknown custom element: <component> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

found in

---> <TransitionGroup>
       <TransitionWrapper>
         <Root>

No error is thrown if transition is used instead of transition-group.


I came across this bug because I was building a re-usable animation component that looks like this:

<template>
  <component
    :is="group ? 'transition-group' : 'transition'"
    @enter="velocityEnter"
    @leave="velocityLeave"
  >
    <slot/>
  </component>
</template>

The component actually seems to work as expected, but the error described above is thrown.

transition

Most helpful comment

transition-group has to render a root-node, which by default, is a <span>,and which ca be customized with the tag attribute.

However - and this is not clearly documented I think - if you are using transition-group through the special is="" attribute, transition-group will actually try and use the tag that you used the is on as the element for the root node:

https://github.com/vuejs/vue/blob/dev/src/platforms/web/runtime/components/transition-group.js#L52

While that may seem confusing, it's actually pretty useful. is="" can be used on any element - it's most often used in that way to turn a <tr> in a DOM-template into a component, since other elements would be hoisted out of the <table> befoe Vue can touch the template:

<tr is="mycomponent">

In terms of transition-group, the usecase would be:

<transition-group tag="li"> 

<!-- has the same result as: -->

<li is="transition-group"> 

<!-- if transitiongroup didn't do what I explained above, 
        you would have to do the following, which feels a bit redundant:
-->
<li is="transition-group" tag="li"> 

Now the consequence of your code is that transition-group actually renders a literal <component> element as it's root node, which is neither a native HTML Element nor a Vue component - it's just a placeholder not meant to be rendered to the DOM, really.

Solution

<span
    :is="group ? 'transition-group' : 'transition'"

/ping @chrisvfritz should we document this?

All 3 comments

transition-group has to render a root-node, which by default, is a <span>,and which ca be customized with the tag attribute.

However - and this is not clearly documented I think - if you are using transition-group through the special is="" attribute, transition-group will actually try and use the tag that you used the is on as the element for the root node:

https://github.com/vuejs/vue/blob/dev/src/platforms/web/runtime/components/transition-group.js#L52

While that may seem confusing, it's actually pretty useful. is="" can be used on any element - it's most often used in that way to turn a <tr> in a DOM-template into a component, since other elements would be hoisted out of the <table> befoe Vue can touch the template:

<tr is="mycomponent">

In terms of transition-group, the usecase would be:

<transition-group tag="li"> 

<!-- has the same result as: -->

<li is="transition-group"> 

<!-- if transitiongroup didn't do what I explained above, 
        you would have to do the following, which feels a bit redundant:
-->
<li is="transition-group" tag="li"> 

Now the consequence of your code is that transition-group actually renders a literal <component> element as it's root node, which is neither a native HTML Element nor a Vue component - it's just a placeholder not meant to be rendered to the DOM, really.

Solution

<span
    :is="group ? 'transition-group' : 'transition'"

/ping @chrisvfritz should we document this?

Hm, I'm wondering how feasible it would be to have transition-group make an exception and still fall back to a span when the tag is component. Then it would behave as expected and there'd be no need to document the gotcha.

@LinusBorg What do you think?

Would be totally feasable as what I described wasn't a default behaviour of Vue, but rather an intentional decision in the code of that component.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

robertleeplummerjr picture robertleeplummerjr  路  3Comments

julianxhokaxhiu picture julianxhokaxhiu  路  3Comments

loki0609 picture loki0609  路  3Comments

fergaldoyle picture fergaldoyle  路  3Comments

hiendv picture hiendv  路  3Comments