The Problem

<TransitionGroup> requires every child to have a unique key. When keys are duplicated, Vue cannot track which items are entering, leaving, or moving, resulting in broken animations and console warnings.

Symptoms

  • Console warning: "Duplicate keys found during transition"
  • List items animate incorrectly (wrong item fades out)
  • Stagger animations apply to wrong elements
  • Items jump to wrong positions during reorder

Real Error Message

bash
[Vue warn]: <TransitionGroup> children must be keyed.
Found duplicate key: "item-3"

Common Causes

Cause 1: Using Index as Key

vue
<TransitionGroup name="list" tag="ul">
  <li v-for="(item, index) in items" :key="index">  <!-- BAD -->
    {{ item.name }}
  </li>
</TransitionGroup>

Cause 2: Non-Unique IDs from Backend

vue
<TransitionGroup name="list" tag="ul">
  <li v-for="item in items" :key="item.category">  <!-- Multiple items share category -->
    {{ item.name }}
  </li>
</TransitionGroup>

How to Fix It

Fix 1: Use Unique IDs

vue
<TransitionGroup name="list" tag="ul">
  <li v-for="item in items" :key="item.id">
    {{ item.name }}
  </li>
</TransitionGroup>

Fix 2: Generate Unique Keys for Items Without IDs

vue
<TransitionGroup name="list" tag="ul">
  <li v-for="(item, index) in items" :key="`item-${item.name}-${index}`">
    {{ item.name }}
  </li>
</TransitionGroup>

Fix 3: Deduplicate Before Rendering

javascript
const uniqueItems = computed(() => {
  const seen = new Set();
  return items.value.filter(item => {
    if (seen.has(item.id)) return false;
    seen.add(item.id);
    return true;
  });
});
vue
<TransitionGroup name="list" tag="ul">
  <li v-for="item in uniqueItems" :key="item.id">
    {{ item.name }}
  </li>
</TransitionGroup>

CSS for Smooth Transitions

css
.list-enter-active,
.list-leave-active {
  transition: all 0.3s ease;
}
.list-enter-from,
.list-leave-to {
  opacity: 0;
  transform: translateY(20px);
}
.list-move {
  transition: transform 0.3s ease;
}