fix: image previews getting stuck in list view when paginating (#12062)
### What? In the List View, row data related to images and relationships gets stuck when you go from one page to another. ### Why? The `key` we are providing is not unique and not triggering the DOM to update. ### How? Uses the `row id` as a unique key prop to each table row to ensure proper re-rendering of rows during pagination. #### Testing Adds e2e test to `upload` test suite. You can recreate the issue using the `upload` test suite and new `list view preview` collection.
This commit is contained in:
committed by
GitHub
parent
101f7658f7
commit
a0fb3353c6
@@ -40,7 +40,14 @@ export const Table: React.FC<Props> = ({ appearance, columns, data }) => {
|
||||
<tbody>
|
||||
{data &&
|
||||
data.map((row, rowIndex) => (
|
||||
<tr className={`row-${rowIndex + 1}`} key={rowIndex}>
|
||||
<tr
|
||||
className={`row-${rowIndex + 1}`}
|
||||
key={
|
||||
typeof row.id === 'string' || typeof row.id === 'number'
|
||||
? String(row.id)
|
||||
: rowIndex
|
||||
}
|
||||
>
|
||||
{activeColumns.map((col, colIndex) => {
|
||||
const { accessor } = col
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { CollectionSlug } from 'payload'
|
||||
|
||||
import path from 'path'
|
||||
import { getFileByPath } from 'payload'
|
||||
import { fileURLToPath } from 'url'
|
||||
@@ -18,6 +20,7 @@ import {
|
||||
enlargeSlug,
|
||||
focalNoSizesSlug,
|
||||
hideFileInputOnCreateSlug,
|
||||
listViewPreviewSlug,
|
||||
mediaSlug,
|
||||
mediaWithoutCacheTagsSlug,
|
||||
mediaWithoutRelationPreviewSlug,
|
||||
@@ -760,6 +763,26 @@ export default buildConfigWithDefaults({
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
slug: listViewPreviewSlug,
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'imageUpload',
|
||||
type: 'upload',
|
||||
relationTo: mediaWithRelationPreviewSlug,
|
||||
displayPreview: true,
|
||||
},
|
||||
{
|
||||
name: 'imageRelationship',
|
||||
type: 'relationship',
|
||||
relationTo: mediaWithRelationPreviewSlug,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
onInit: async (payload) => {
|
||||
const uploadsDir = path.resolve(dirname, './media')
|
||||
@@ -932,6 +955,22 @@ export default buildConfigWithDefaults({
|
||||
},
|
||||
file: imageFile,
|
||||
})
|
||||
|
||||
for (let i = 0; i < 20; i++) {
|
||||
const data = {
|
||||
title: `List View Preview ${i + 1}`,
|
||||
imageUpload: uploadedImageWithPreview,
|
||||
imageRelationship: uploadedImageWithPreview,
|
||||
}
|
||||
if (i > 15) {
|
||||
data.imageUpload = ''
|
||||
data.imageRelationship = ''
|
||||
}
|
||||
await payload.create({
|
||||
collection: listViewPreviewSlug as CollectionSlug,
|
||||
data,
|
||||
})
|
||||
}
|
||||
},
|
||||
serverURL: undefined,
|
||||
upload: {
|
||||
|
||||
@@ -31,6 +31,7 @@ import {
|
||||
customUploadFieldSlug,
|
||||
focalOnlySlug,
|
||||
hideFileInputOnCreateSlug,
|
||||
listViewPreviewSlug,
|
||||
mediaSlug,
|
||||
mediaWithoutCacheTagsSlug,
|
||||
relationPreviewSlug,
|
||||
@@ -55,6 +56,7 @@ let relationURL: AdminUrlUtil
|
||||
let adminThumbnailSizeURL: AdminUrlUtil
|
||||
let adminThumbnailFunctionURL: AdminUrlUtil
|
||||
let adminThumbnailWithSearchQueriesURL: AdminUrlUtil
|
||||
let listViewPreviewURL: AdminUrlUtil
|
||||
let mediaWithoutCacheTagsSlugURL: AdminUrlUtil
|
||||
let focalOnlyURL: AdminUrlUtil
|
||||
let withMetadataURL: AdminUrlUtil
|
||||
@@ -89,6 +91,7 @@ describe('Uploads', () => {
|
||||
serverURL,
|
||||
adminThumbnailWithSearchQueries,
|
||||
)
|
||||
listViewPreviewURL = new AdminUrlUtil(serverURL, listViewPreviewSlug)
|
||||
mediaWithoutCacheTagsSlugURL = new AdminUrlUtil(serverURL, mediaWithoutCacheTagsSlug)
|
||||
focalOnlyURL = new AdminUrlUtil(serverURL, focalOnlySlug)
|
||||
withMetadataURL = new AdminUrlUtil(serverURL, withMetadataSlug)
|
||||
@@ -1400,4 +1403,30 @@ describe('Uploads', () => {
|
||||
await expect(thumbnail).toHaveAttribute('src', '/api/focal-only/file/small.png')
|
||||
})
|
||||
})
|
||||
|
||||
test('should show correct image preview or placeholder after paginating', async () => {
|
||||
await page.goto(listViewPreviewURL.list)
|
||||
const firstRow = page.locator('.row-1')
|
||||
|
||||
const imageUploadCell = firstRow.locator('.cell-imageUpload .relationship-cell')
|
||||
await expect(imageUploadCell).toHaveText('<No Image Upload>')
|
||||
|
||||
const imageRelationshipCell = firstRow.locator('.cell-imageRelationship .relationship-cell')
|
||||
await expect(imageRelationshipCell).toHaveText('<No Image Relationship>')
|
||||
|
||||
const pageTwoButton = page.locator('.paginator__page', { hasText: '2' })
|
||||
await expect(pageTwoButton).toBeVisible()
|
||||
await pageTwoButton.click()
|
||||
|
||||
const imageUploadImg = imageUploadCell.locator('.thumbnail')
|
||||
await expect(imageUploadImg).toBeVisible()
|
||||
await expect(imageRelationshipCell).toHaveText('image-1.png')
|
||||
|
||||
const pageOneButton = page.locator('.paginator__page', { hasText: '1' })
|
||||
await expect(pageOneButton).toBeVisible()
|
||||
await pageOneButton.click()
|
||||
|
||||
await expect(imageUploadCell).toHaveText('<No Image Upload>')
|
||||
await expect(imageRelationshipCell).toHaveText('<No Image Relationship>')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -22,3 +22,5 @@ export const withMetadataSlug = 'with-meta-data'
|
||||
export const withoutMetadataSlug = 'without-meta-data'
|
||||
export const withOnlyJPEGMetadataSlug = 'with-only-jpeg-meta-data'
|
||||
export const customFileNameMediaSlug = 'custom-file-name-media'
|
||||
|
||||
export const listViewPreviewSlug = 'list-view-preview'
|
||||
|
||||
Reference in New Issue
Block a user