{"record":{"id":"6cc34d7b6ae14161","repo":"Meituan-Dianping/mpvue","slug":"transition-group-children-must-be-keyed-name","errorCode":null,"errorMessage":"<transition-group> children must be keyed: <${name}>","messagePattern":"<transition-group> children must be keyed: <(.+?)>","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/platforms/web/runtime/components/transition-group.js","lineNumber":54,"sourceCode":"  render (h: Function) {\n    const tag: string = this.tag || this.$vnode.data.tag || 'span'\n    const map: Object = Object.create(null)\n    const prevChildren: Array<VNode> = this.prevChildren = this.children\n    const rawChildren: Array<VNode> = this.$slots.default || []\n    const children: Array<VNode> = this.children = []\n    const transitionData: Object = extractTransitionData(this)\n\n    for (let i = 0; i < rawChildren.length; i++) {\n      const c: VNode = rawChildren[i]\n      if (c.tag) {\n        if (c.key != null && String(c.key).indexOf('__vlist') !== 0) {\n          children.push(c)\n          map[c.key] = c\n          ;(c.data || (c.data = {})).transition = transitionData\n        } else if (process.env.NODE_ENV !== 'production') {\n          const opts: ?VNodeComponentOptions = c.componentOptions\n          const name: string = opts ? (opts.Ctor.options.name || opts.tag || '') : c.tag\n          warn(`<transition-group> children must be keyed: <${name}>`)\n        }\n      }\n    }\n\n    if (prevChildren) {\n      const kept: Array<VNode> = []\n      const removed: Array<VNode> = []\n      for (let i = 0; i < prevChildren.length; i++) {\n        const c: VNode = prevChildren[i]\n        c.data.transition = transitionData\n        c.data.pos = c.elm.getBoundingClientRect()\n        if (map[c.key]) {\n          kept.push(c)\n        } else {\n          removed.push(c)\n        }\n      }\n      this.kept = h(tag, null, kept)","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/Meituan-Dianping/mpvue/blob/6c5d78ee04f58c6d782c456dfcf0fe63c0b7f89b/src/platforms/web/runtime/components/transition-group.js#L36-L72","documentation":"<transition-group> implements FLIP-based move animations that require tracking each child by its `key`. During render it builds a children map keyed by `c.key`; if a child has no key it cannot be tracked, so in development Vue warns that transition-group children must be keyed, printing the child's component or tag name.","triggerScenarios":"Rendering a list inside <transition-group> with v-for but no `:key` binding; rendering static, unkeyed elements as direct children of transition-group; v-for over objects where the key expression is undefined for some items.","commonSituations":"Forgetting `:key=\"item.id\"` when adding transition-group to an existing v-for; keys bound to the loop index and then removed during refactors; conditional children (v-if) without keys inside a transition-group.","solutions":["Add a unique `:key` to every child rendered inside <transition-group>, e.g. `:key=\"item.id\"` on the v-for element.","Use a stable unique identifier (id from data), not the array index, so move/remove animations track correctly.","Key any hardcoded/conditional children too (e.g. `<span key=\"label\">`).","If the list is truly static and needs no animation, use a plain container instead of transition-group."],"exampleFix":"// before\n<transition-group name=\"list\">\n  <li v-for=\"item in items\">{{ item.name }}</li>\n</transition-group>\n// after\n<transition-group name=\"list\">\n  <li v-for=\"item in items\" :key=\"item.id\">{{ item.name }}</li>\n</transition-group>","handlingStrategy":"validation","validationCode":"// before rendering, verify every list item has a key source\nitems.forEach((item, i) => {\n  if (item.id == null) console.warn('transition-group child at index ' + i + ' has no unique id for :key')\n})","typeGuard":"const hasKey = c => c && c.key != null\nif (!children.every(hasKey)) console.warn('all transition-group children need :key')","tryCatchPattern":null,"preventionTips":["Always pair v-for inside transition-group with :key.","Use stable unique ids, never the array index.","Key hardcoded and v-if/v-else children inside transition-group too.","Enable dev-mode linting (eslint-plugin-vue 'require-v-for-key') to catch this at lint time."],"tags":["vue","transition-group","v-for","key","animation"],"backgroundTag":"missing-list-key","analyzedSha":"6c5d78ee04f58c6d782c456dfcf0fe63c0b7f89b","analyzedAt":"2026-09-02T05:17:40.946Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T11:17:12.671Z"}