fix: avoid flushSync call during <EditorContent /> lifecycle

This commit is contained in:
R R 2025-05-03 18:38:55 +02:00
parent aff018e651
commit 1f5a830e5b
3 changed files with 8 additions and 39 deletions

View File

@ -3,7 +3,7 @@ import { ReactPortal } from 'react'
import { ReactRenderer } from './ReactRenderer.js'
export type EditorWithContentComponent = Editor & { contentComponent?: ContentComponent | null }
export type EditorWithContentComponent = Editor & { contentComponent?: ContentComponent | null; isEditorContentInitialized?: boolean }
export type ContentComponent = {
setRenderer(id: string, renderer: ReactRenderer): void;
removeRenderer(id: string): void;

View File

@ -98,18 +98,9 @@ export class PureEditorContent extends React.Component<
> {
editorContentRef: React.RefObject<any>
initialized: boolean
unsubscribeToContentComponent?: () => void
constructor(props: EditorContentProps) {
super(props)
this.editorContentRef = React.createRef()
this.initialized = false
this.state = {
hasContentComponentInitialized: Boolean((props.editor as EditorWithContentComponent | null)?.contentComponent),
}
}
componentDidMount() {
@ -138,29 +129,11 @@ export class PureEditorContent extends React.Component<
editor.contentComponent = getInstance()
// Has the content component been initialized?
if (!this.state.hasContentComponentInitialized) {
// Subscribe to the content component
this.unsubscribeToContentComponent = editor.contentComponent.subscribe(() => {
this.setState(prevState => {
if (!prevState.hasContentComponentInitialized) {
return {
hasContentComponentInitialized: true,
}
}
return prevState
})
// Unsubscribe to previous content component
if (this.unsubscribeToContentComponent) {
this.unsubscribeToContentComponent()
}
})
}
editor.createNodeViews()
this.initialized = true
editor.isEditorContentInitialized = true
this.forceUpdate()
}
}
@ -171,7 +144,7 @@ export class PureEditorContent extends React.Component<
return
}
this.initialized = false
editor.isEditorContentInitialized = false
if (!editor.isDestroyed) {
editor.view.setProps({
@ -179,10 +152,6 @@ export class PureEditorContent extends React.Component<
})
}
if (this.unsubscribeToContentComponent) {
this.unsubscribeToContentComponent()
}
editor.contentComponent = null
if (!editor.options.element.firstChild) {

View File

@ -78,7 +78,7 @@ type ComponentType<R, P> =
export class ReactRenderer<R = unknown, P extends Record<string, any> = object> {
id: string
editor: Editor
editor: EditorWithContentComponent
component: any
@ -101,7 +101,7 @@ export class ReactRenderer<R = unknown, P extends Record<string, any> = object>
}: ReactRendererOptions) {
this.id = Math.floor(Math.random() * 0xFFFFFFFF).toString()
this.component = component
this.editor = editor as EditorWithContentComponent
this.editor = editor
this.props = props as P
this.element = document.createElement(as)
this.element.classList.add('react-renderer')
@ -110,7 +110,7 @@ export class ReactRenderer<R = unknown, P extends Record<string, any> = object>
this.element.classList.add(...className.split(' '))
}
if (this.editor.isInitialized) {
if (this.editor.isEditorContentInitialized) {
// On first render, we need to flush the render synchronously
// Renders afterwards can be async, but this fixes a cursor positioning issue
flushSync(() => {