Skip to content

Commit d020c7f

Browse files
committed
fix(VFileUpload): stabilize item keys to correctly remove using chips
resolves #21772
1 parent 63305d0 commit d020c7f

3 files changed

Lines changed: 19 additions & 4 deletions

File tree

packages/vuetify/src/labs/VFileUpload/VFileUploadDropzone.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { useLocale } from '@/composables/locale'
1818
// Utilities
1919
import { inject, ref, shallowRef, toRef } from 'vue'
2020
import { genericComponent, pick, propsFactory, useRender } from '@/util'
21+
import { getFileKey } from './fileKey'
2122

2223
// Types
2324
import type { InjectionKey, PropType, Ref } from 'vue'
@@ -267,6 +268,7 @@ export const VFileUploadDropzone = genericComponent<VFileUploadDropzoneSlots>()(
267268
)
268269
) : (
269270
modelValue.map((file, i) => {
271+
const key = getFileKey(file)
270272
const slotProps = {
271273
file,
272274
props: {
@@ -276,7 +278,7 @@ export const VFileUploadDropzone = genericComponent<VFileUploadDropzoneSlots>()(
276278

277279
return (
278280
<VDefaultsProvider
279-
key={ i }
281+
key={ key }
280282
defaults={{
281283
VFileUploadItem: {
282284
file,
@@ -289,7 +291,7 @@ export const VFileUploadDropzone = genericComponent<VFileUploadDropzoneSlots>()(
289291
>
290292
{ slots.item?.(slotProps) ?? (
291293
<VFileUploadItem
292-
key={ i }
294+
key={ key }
293295
onClick:remove={ () => onClickRemove(i) }
294296
/>
295297
)}

packages/vuetify/src/labs/VFileUpload/VFileUploadList.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { makeVListProps, VList } from '@/components/VList/VList'
77
// Utilities
88
import { inject } from 'vue'
99
import { genericComponent, propsFactory, useRender } from '@/util'
10+
import { getFileKey } from './fileKey'
1011

1112
// Types
1213
import type { PropType } from 'vue'
@@ -62,6 +63,7 @@ export const VFileUploadList = genericComponent<VFileUploadListSlots>()({
6263
bgColor="transparent"
6364
>
6465
{ slots.default?.({ files, onClickRemove: (i: number) => context?.onClickRemove(i) }) ?? files.map((file, index) => {
66+
const key = getFileKey(file)
6567
const slotProps = {
6668
file,
6769
props: {
@@ -71,7 +73,7 @@ export const VFileUploadList = genericComponent<VFileUploadListSlots>()({
7173

7274
return (
7375
<VDefaultsProvider
74-
key={ index }
76+
key={ key }
7577
defaults={{
7678
VFileUploadItem: {
7779
file,
@@ -84,7 +86,7 @@ export const VFileUploadList = genericComponent<VFileUploadListSlots>()({
8486
>
8587
{ slots.item?.(slotProps) ?? (
8688
<VFileUploadItem
87-
key={ index }
89+
key={ key }
8890
onClick:remove={ () => context?.onClickRemove(index) }
8991
/>
9092
)}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
let nextId = 0
2+
const fileIds = new WeakMap<File, number>()
3+
4+
export function getFileKey (file: File): number {
5+
let id = fileIds.get(file)
6+
if (id == null) {
7+
id = ++nextId
8+
fileIds.set(file, id)
9+
}
10+
return id
11+
}

0 commit comments

Comments
 (0)