fix(ui): link element triggering clicks twice (#11362)
Fixes https://github.com/payloadcms/payload/issues/11359#issuecomment-2678213414 The link element by using startTransitionRoute and manually calling router.push would technically cause links to be clicked twice, by not preventing default browser behaviour. This caused a problem on clicking /create links as it hit the route twice. Added a test making sure Create new doesn't lead to abnormally increased document counts Changes: - Added `e.preventDefault()` in our Link element - Added `preventDefault` as an optional prop to this element so that people can handle it on their own if needed via a custom `onClick`
This commit is contained in:
@@ -23,10 +23,20 @@ function isModifiedEvent(event: React.MouseEvent): boolean {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Link: React.FC<Parameters<typeof NextLink>[0]> = ({
|
type Props = {
|
||||||
|
/**
|
||||||
|
* Disable the e.preventDefault() call on click if you want to handle it yourself via onClick
|
||||||
|
*
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
preventDefault?: boolean
|
||||||
|
} & Parameters<typeof NextLink>[0]
|
||||||
|
|
||||||
|
export const Link: React.FC<Props> = ({
|
||||||
children,
|
children,
|
||||||
href,
|
href,
|
||||||
onClick,
|
onClick,
|
||||||
|
preventDefault = true,
|
||||||
ref,
|
ref,
|
||||||
replace,
|
replace,
|
||||||
scroll,
|
scroll,
|
||||||
@@ -47,6 +57,12 @@ export const Link: React.FC<Parameters<typeof NextLink>[0]> = ({
|
|||||||
onClick(e)
|
onClick(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We need a preventDefault here so that a clicked link doesn't trigger twice,
|
||||||
|
// once for default browser navigation and once for startRouteTransition
|
||||||
|
if (preventDefault) {
|
||||||
|
e.preventDefault()
|
||||||
|
}
|
||||||
|
|
||||||
startRouteTransition(() => {
|
startRouteTransition(() => {
|
||||||
const url = typeof href === 'string' ? href : formatUrl(href)
|
const url = typeof href === 'string' ? href : formatUrl(href)
|
||||||
|
|
||||||
|
|||||||
@@ -438,6 +438,47 @@ describe('Versions', () => {
|
|||||||
await expect(drawer.locator('.id-label')).toBeVisible()
|
await expect(drawer.locator('.id-label')).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('collection - autosave - should not create duplicates when clicking Create new', async () => {
|
||||||
|
// This test checks that when we click "Create new" in the list view, it only creates 1 extra document and not more
|
||||||
|
const { totalDocs: initialDocsCount } = await payload.find({
|
||||||
|
collection: autosaveCollectionSlug,
|
||||||
|
draft: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
await page.goto(autosaveURL.create)
|
||||||
|
await page.locator('#field-title').fill('autosave title')
|
||||||
|
await waitForAutoSaveToRunAndComplete(page)
|
||||||
|
await expect(page.locator('#field-title')).toHaveValue('autosave title')
|
||||||
|
|
||||||
|
const { totalDocs: updatedDocsCount } = await payload.find({
|
||||||
|
collection: autosaveCollectionSlug,
|
||||||
|
draft: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
await expect(() => {
|
||||||
|
expect(updatedDocsCount).toBe(initialDocsCount + 1)
|
||||||
|
}).toPass({ timeout: POLL_TOPASS_TIMEOUT, intervals: [100] })
|
||||||
|
|
||||||
|
await page.goto(autosaveURL.list)
|
||||||
|
const createNewButton = page.locator('.list-header .btn:has-text("Create New")')
|
||||||
|
await createNewButton.click()
|
||||||
|
|
||||||
|
await page.waitForURL(`**/${autosaveCollectionSlug}/**`)
|
||||||
|
|
||||||
|
await page.locator('#field-title').fill('autosave title')
|
||||||
|
await waitForAutoSaveToRunAndComplete(page)
|
||||||
|
await expect(page.locator('#field-title')).toHaveValue('autosave title')
|
||||||
|
|
||||||
|
const { totalDocs: latestDocsCount } = await payload.find({
|
||||||
|
collection: autosaveCollectionSlug,
|
||||||
|
draft: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
await expect(() => {
|
||||||
|
expect(latestDocsCount).toBe(updatedDocsCount + 1)
|
||||||
|
}).toPass({ timeout: POLL_TOPASS_TIMEOUT, intervals: [100] })
|
||||||
|
})
|
||||||
|
|
||||||
test('collection - should update updatedAt', async () => {
|
test('collection - should update updatedAt', async () => {
|
||||||
await page.goto(url.create)
|
await page.goto(url.create)
|
||||||
await page.waitForURL(`**/${url.create}`)
|
await page.waitForURL(`**/${url.create}`)
|
||||||
@@ -757,7 +798,7 @@ describe('Versions', () => {
|
|||||||
|
|
||||||
// schedule publish should not be available before document has been saved
|
// schedule publish should not be available before document has been saved
|
||||||
await page.locator('#action-save-popup').click()
|
await page.locator('#action-save-popup').click()
|
||||||
await expect(page.locator('#schedule-publish')).not.toBeVisible()
|
await expect(page.locator('#schedule-publish')).toBeHidden()
|
||||||
|
|
||||||
// save draft then try to schedule publish
|
// save draft then try to schedule publish
|
||||||
await saveDocAndAssert(page)
|
await saveDocAndAssert(page)
|
||||||
|
|||||||
Reference in New Issue
Block a user