Merge pull request #5549 from payloadcms/temp33
fix: unload client functions after unmount (e.g. leaving document)
This commit is contained in:
@@ -1,18 +1,24 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
type AddClientFunctionContextType = (func: any) => void
|
||||
type ModifyClientFunctionContextType = {
|
||||
addClientFunction: (args: ModifyFunctionArgs) => void
|
||||
removeClientFunction: (args: ModifyFunctionArgs) => void
|
||||
}
|
||||
type ClientFunctionsContextType = Record<string, any>
|
||||
|
||||
const AddClientFunctionContext = React.createContext<AddClientFunctionContextType>(() => null)
|
||||
const ModifyClientFunctionContext = React.createContext<ModifyClientFunctionContextType>({
|
||||
addClientFunction: () => null,
|
||||
removeClientFunction: () => null,
|
||||
})
|
||||
const ClientFunctionsContext = React.createContext<ClientFunctionsContextType>({})
|
||||
|
||||
type AddFunctionArgs = { func: any; key: string }
|
||||
type ModifyFunctionArgs = { func: any; key: string }
|
||||
|
||||
export const ClientFunctionProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
const [clientFunctions, setClientFunctions] = React.useState({})
|
||||
|
||||
const addClientFunction = React.useCallback((args: AddFunctionArgs) => {
|
||||
const addClientFunction = React.useCallback((args: ModifyFunctionArgs) => {
|
||||
setClientFunctions((state) => {
|
||||
const newState = { ...state }
|
||||
newState[args.key] = args.func
|
||||
@@ -20,24 +26,44 @@ export const ClientFunctionProvider: React.FC<{ children: React.ReactNode }> = (
|
||||
})
|
||||
}, [])
|
||||
|
||||
const removeClientFunction = React.useCallback((args: ModifyFunctionArgs) => {
|
||||
setClientFunctions((state) => {
|
||||
const newState = { ...state }
|
||||
delete newState[args.key]
|
||||
return newState
|
||||
})
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<AddClientFunctionContext.Provider value={addClientFunction}>
|
||||
<ModifyClientFunctionContext.Provider
|
||||
value={{
|
||||
addClientFunction,
|
||||
removeClientFunction,
|
||||
}}
|
||||
>
|
||||
<ClientFunctionsContext.Provider value={clientFunctions}>
|
||||
{children}
|
||||
</ClientFunctionsContext.Provider>
|
||||
</AddClientFunctionContext.Provider>
|
||||
</ModifyClientFunctionContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useAddClientFunction = (key: string, func: any) => {
|
||||
const addClientFunction = React.useContext(AddClientFunctionContext)
|
||||
const { addClientFunction, removeClientFunction } = React.useContext(ModifyClientFunctionContext)
|
||||
|
||||
React.useEffect(() => {
|
||||
addClientFunction({
|
||||
func,
|
||||
key,
|
||||
})
|
||||
}, [func, key, addClientFunction])
|
||||
|
||||
return () => {
|
||||
removeClientFunction({
|
||||
func,
|
||||
key,
|
||||
})
|
||||
}
|
||||
}, [func, key, addClientFunction, removeClientFunction])
|
||||
}
|
||||
|
||||
export const useClientFunctions = () => {
|
||||
|
||||
@@ -28,9 +28,15 @@ let client: RESTClient
|
||||
let page: Page
|
||||
let serverURL: string
|
||||
|
||||
async function navigateToLexicalFields() {
|
||||
/**
|
||||
* Client-side navigation to the lexical editor from list view
|
||||
*/
|
||||
async function navigateToLexicalFields(navigateToListView: boolean = true) {
|
||||
if (navigateToListView) {
|
||||
const url: AdminUrlUtil = new AdminUrlUtil(serverURL, 'lexical-fields')
|
||||
await page.goto(url.list)
|
||||
}
|
||||
|
||||
const linkToDoc = page.locator('tbody tr:first-child .cell-title a').first()
|
||||
await expect(() => expect(linkToDoc).toBeTruthy()).toPass({ timeout: POLL_TOPASS_TIMEOUT })
|
||||
const linkDocHref = await linkToDoc.getAttribute('href')
|
||||
@@ -718,8 +724,7 @@ describe('lexical', () => {
|
||||
await expect(nestedEditorParagraph).toHaveText('Some text below relationship node 12345')
|
||||
})
|
||||
|
||||
test('should respect row removal in nested array field', async () => {
|
||||
await navigateToLexicalFields()
|
||||
const shouldRespectRowRemovalTest = async () => {
|
||||
const richTextField = page.locator('.rich-text-lexical').nth(1) // second
|
||||
await richTextField.scrollIntoViewIfNeeded()
|
||||
await expect(richTextField).toBeVisible()
|
||||
@@ -762,6 +767,36 @@ describe('lexical', () => {
|
||||
await saveDocAndAssert(page)
|
||||
|
||||
await expect(page.locator('.Toastify')).not.toContainText('Please correct invalid fields.')
|
||||
}
|
||||
|
||||
// eslint-disable-next-line playwright/expect-expect
|
||||
test('should respect row removal in nested array field', async () => {
|
||||
await navigateToLexicalFields()
|
||||
await shouldRespectRowRemovalTest()
|
||||
})
|
||||
|
||||
test('should respect row removal in nested array field after navigating away from lexical document, then navigating back', async () => {
|
||||
// This test verifies an issue where a lexical editor with blocks disappears when navigating away from the lexical document, then navigating back, without a hard refresh
|
||||
await navigateToLexicalFields()
|
||||
|
||||
// Wait for lexical to be loaded up fully
|
||||
const richTextField = page.locator('.rich-text-lexical').nth(1) // second
|
||||
await richTextField.scrollIntoViewIfNeeded()
|
||||
await expect(richTextField).toBeVisible()
|
||||
|
||||
const conditionalArrayBlock = richTextField.locator('.lexical-block').nth(7)
|
||||
|
||||
await conditionalArrayBlock.scrollIntoViewIfNeeded()
|
||||
await expect(conditionalArrayBlock).toBeVisible()
|
||||
|
||||
// navigate to list view
|
||||
await page.locator('.step-nav a').nth(1).click()
|
||||
await page.waitForURL('**/lexical-fields?limit=10')
|
||||
|
||||
// Click on lexical document in list view (navigateToLexicalFields is client-side navigation which is what we need to reproduce the issue here)
|
||||
await navigateToLexicalFields(false)
|
||||
|
||||
await shouldRespectRowRemovalTest()
|
||||
})
|
||||
|
||||
test.skip('should respect required error state in deeply nested text field', async () => {
|
||||
|
||||
Reference in New Issue
Block a user