fix(richtext-lexical): ensure initial state for nested lexical fields (#11837)

Lexical fields nested in other fields (e.g. groups, blocks, arrays) did
not have their initial sub-field states generated, leading in multiple
client-side fetches to fetch initial state when the page is loaded.

Before:


https://github.com/user-attachments/assets/c1d808ef-1bd3-4fb1-a9d6-d5ef81cef16d

After:


https://github.com/user-attachments/assets/0dcda515-ce68-4107-ba29-a08fff851ae3
This commit is contained in:
Alessio Gravili
2025-03-24 14:08:26 -06:00
committed by GitHub
parent 8d374cb57d
commit fb01b4046d
4 changed files with 73 additions and 2 deletions

View File

@@ -50,7 +50,7 @@ export const RscEntryLexicalField: React.FC<
}) })
let initialLexicalFormState = {} let initialLexicalFormState = {}
if (args.data?.[field.name]?.root?.children?.length) { if (args.siblingData?.[field.name]?.root?.children?.length) {
initialLexicalFormState = await buildInitialState({ initialLexicalFormState = await buildInitialState({
context: { context: {
id: args.id, id: args.id,
@@ -66,7 +66,7 @@ export const RscEntryLexicalField: React.FC<
renderFieldFn: renderField, renderFieldFn: renderField,
req: args.req, req: args.req,
}, },
nodeData: args.data?.[field.name]?.root?.children as SerializedLexicalNode[], nodeData: args.siblingData?.[field.name]?.root?.children as SerializedLexicalNode[],
}) })
} }

View File

@@ -1507,6 +1507,24 @@ describe('lexicalBlocks', () => {
), ),
).toHaveText('Some Description') ).toHaveText('Some Description')
}) })
test('ensure individual inline blocks in lexical editor within a block have initial state on initial load', async () => {
await page.goto('http://localhost:3000/admin/collections/LexicalInBlock?limit=10')
await assertNetworkRequests(
page,
'/collections/LexicalInBlock/',
async () => {
await page.locator('.cell-id a').first().click()
await page.waitForURL(`**/collections/LexicalInBlock/**`)
await expect(
page.locator('.inline-block:has-text("Inline Block In Lexical")'),
).toHaveCount(20)
},
{ allowedNumberOfRequests: 1 },
)
})
}) })
describe('inline blocks', () => { describe('inline blocks', () => {

View File

@@ -42,6 +42,23 @@ export const LexicalInBlock: CollectionConfig = {
{ {
name: 'lexical', name: 'lexical',
type: 'richText', type: 'richText',
editor: lexicalEditor({
features: [
BlocksFeature({
inlineBlocks: [
{
slug: 'inlineBlockInLexical',
fields: [
{
name: 'text',
type: 'text',
},
],
},
],
}),
],
}),
}, },
], ],
}, },

View File

@@ -511,6 +511,16 @@ export const seed = async (_payload: Payload) => {
depth: 0, depth: 0,
}) })
const getInlineBlock = () => ({
type: 'inlineBlock',
fields: {
id: Math.random().toString(36).substring(2, 15),
text: 'text',
blockType: 'inlineBlockInLexical',
},
version: 1,
})
await _payload.create({ await _payload.create({
collection: 'LexicalInBlock', collection: 'LexicalInBlock',
depth: 0, depth: 0,
@@ -548,6 +558,32 @@ export const seed = async (_payload: Payload) => {
blockName: '2', blockName: '2',
lexical: textToLexicalJSON({ text: '2' }), lexical: textToLexicalJSON({ text: '2' }),
}, },
{
blockType: 'lexicalInBlock2',
lexical: {
root: {
children: [
{
children: [...Array.from({ length: 20 }, () => getInlineBlock())],
direction: null,
format: '',
indent: 0,
type: 'paragraph',
version: 1,
textFormat: 0,
textStyle: '',
},
],
direction: null,
format: '',
indent: 0,
type: 'root',
version: 1,
},
},
id: '67e1af0b78de3228e23ef1d5',
blockName: '1',
},
], ],
}, },
}) })