Skip to content

Commit

Permalink
perf(richtext-lexical)!: significantly reduce lexical rerendering and…
Browse files Browse the repository at this point in the history
… amount of network requests from blocks (#9255)

The field RSC now provides an initial state for all lexical blocks. This
completely obliterates any flashes and lexical block loading states when
loading or saving a document.

Previously, when a document is loaded or saved, every lexical block was
sending a network request in order to fetch their form state. Now, this
is batched and handled in the lexical server component. All lexical
block form states are sent to the client together with the parent
lexical field, and are thus available immediately.

We also do the same with block collapsed preferences. Thus, there are no
loading states or layout shifts/flashes of blocks anymore.

Additionally, when saving a document while your cursor is inside a
lexical field, the cursor position is preserved. Previously, a document
save would kick your cursor out of the lexical field.

## Look at how nice this is:


https://github.com/user-attachments/assets/21d736d4-8f80-4df0-a782-7509edd993da

**BREAKING:**

This removes the `feature.hooks.load` and `feature.hooks.save`
interfaces from custom lexical features, as they weren't used internally
and added unnecessary, additional overhead.

If you have custom features that use those, you can migrate to using
normal payload hooks that run on the server instead of the client.
  • Loading branch information
AlessioGr authored Nov 17, 2024
1 parent abe4cc8 commit 35917c6
Show file tree
Hide file tree
Showing 20 changed files with 394 additions and 302 deletions.
8 changes: 7 additions & 1 deletion packages/payload/src/admin/forms/Field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import type { MarkOptional } from 'ts-essentials'

import type { SanitizedFieldPermissions, User } from '../../auth/types.js'
import type { ClientBlock, ClientField, Field } from '../../fields/config/types.js'
import type { Payload } from '../../types/index.js'
import type { DocumentPreferences } from '../../preferences/types.js'
import type { Operation, Payload, PayloadRequest } from '../../types/index.js'
import type {
ClientTab,
Data,
Expand Down Expand Up @@ -66,6 +67,7 @@ export type FieldPaths = {

export type ServerComponentProps = {
clientField: ClientFieldWithOptionalType
collectionSlug: string
data: Data
field: Field
/**
Expand All @@ -78,8 +80,12 @@ export type ServerComponentProps = {
*/
formState: FormState
i18n: I18nClient
id?: number | string
operation: Operation
payload: Payload
permissions: SanitizedFieldPermissions
preferences: DocumentPreferences
req: PayloadRequest
siblingData: Data
user: User
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
'use client'
import type { ClientField, FormState } from 'payload'

import { RenderFields } from '@payloadcms/ui'
import { RenderFields, useFormSubmitted } from '@payloadcms/ui'
import React, { createContext, useMemo } from 'react'

import type { BlockFields } from '../../server/nodes/BlocksNode.js'

import { useFormSave } from './FormSavePlugin.js'

type Props = {
baseClass: string
BlockDrawer: React.FC
Expand All @@ -24,11 +20,11 @@ type Props = {
}>
CustomBlock: React.ReactNode
EditButton: React.FC
formData: BlockFields
errorCount: number
formSchema: ClientField[]
initialState: false | FormState | undefined
nodeKey: string

nodeKey: string
RemoveButton: React.FC
}

Expand Down Expand Up @@ -66,14 +62,16 @@ export const BlockContent: React.FC<Props> = (props) => {
Collapsible,
CustomBlock,
EditButton,
formData,
errorCount,
formSchema,
initialState,
nodeKey,
RemoveButton,
} = props

const { errorCount, fieldHasErrors } = useFormSave({ disabled: !initialState, formData, nodeKey })
const hasSubmitted = useFormSubmitted()

const fieldHasErrors = hasSubmitted && errorCount > 0

const CollapsibleWithErrorProps = useMemo(
() =>
Expand Down

This file was deleted.

Loading

0 comments on commit 35917c6

Please sign in to comment.