Files
stack/packages/mosaic/framework/skills/vue-best-practices/reference/transition-group-key-requirement.md
fargo 1a822493ba format: apply repo prettier (3.8.1) to the folded skills tree
963 markdown files reformatted with the repository's pinned prettier so
pnpm format:check covers the folded tree like every other repo file.

The formatter's embedded-language pass also normalized code fences
(TS semicolons, closed HTML tags in examples, lowercased CSS hex colors,
one renumbered list that skipped an index). Alphanumeric token deltas vs
the fold commit were audited file-by-file; all are formatter-equivalent
markup normalizations plus the four sanitized skills.
2026-08-19 14:37:17 -05:00

3.2 KiB

title, impact, impactDescription, type, tags
title impact impactDescription type tags
TransitionGroup Children Must Have Unique Keys HIGH Missing or non-unique keys cause broken animations and Vue warnings gotcha
vue3
transition-group
animation
key
v-for
list-animation

TransitionGroup Children Must Have Unique Keys

Impact: HIGH - Unlike regular <Transition>, the <TransitionGroup> component always requires a unique key attribute on every child element. Without keys, Vue cannot track individual items, animations will break, and you'll see console warnings.

This is a fundamental difference from <Transition> which works on single elements. Since <TransitionGroup> animates lists of elements, Vue needs keys to track which items are entering, leaving, or moving.

Task Checklist

  • Ensure every direct child of <TransitionGroup> has a unique key attribute
  • Use stable identifiers (IDs) rather than array indices for keys
  • Do not use the same key for different items at different times
  • When using v-for, always include :key binding

Incorrect - Missing keys:

<template>
  <!-- WRONG: Missing keys causes broken animations -->
  <TransitionGroup name="list" tag="ul">
    <li v-for="item in items">
      {{ item.name }}
    </li>
  </TransitionGroup>
</template>

Incorrect - Using index as key:

<template>
  <!-- PROBLEMATIC: Index keys cause incorrect animations when list changes -->
  <TransitionGroup name="list" tag="ul">
    <li v-for="(item, index) in items" :key="index">
      {{ item.name }}
    </li>
  </TransitionGroup>
</template>

When using index as key:

  • If you remove item at index 2, what was index 3 becomes index 2
  • Vue thinks index 2 changed content rather than being removed
  • Animations fire on wrong elements

Correct - Unique stable keys:

<template>
  <!-- CORRECT: Unique ID keys for proper tracking -->
  <TransitionGroup name="list" tag="ul">
    <li v-for="item in items" :key="item.id">
      {{ item.name }}
    </li>
  </TransitionGroup>
</template>

Correct - Keys on static children:

<template>
  <!-- CORRECT: Even static children need keys in TransitionGroup -->
  <TransitionGroup name="fade" tag="div">
    <span v-if="showA" key="a">Content A</span>
    <span v-if="showB" key="b">Content B</span>
    <span v-if="showC" key="c">Content C</span>
  </TransitionGroup>
</template>

Common Error Messages

Without keys, you'll see warnings like:

[Vue warn]: <TransitionGroup> children must be keyed.

With Draggable Libraries

When using <TransitionGroup> with libraries like vue.draggable.next, key issues can cause errors:

// Error you might see without proper keys
TypeError: domElement is null

Ensure all draggable items have unique keys:

<template>
  <draggable v-model="items" item-key="id">
    <template #item="{ element }">
      <TransitionGroup name="list" tag="div">
        <div :key="element.id">{{ element.name }}</div>
      </TransitionGroup>
    </template>
  </draggable>
</template>

Reference