Skip to content

Commit

Permalink
fix(lexical-editor): update editor state via UpdateStatePlugin (#3650)
Browse files Browse the repository at this point in the history
  • Loading branch information
Pavel910 authored Nov 1, 2023
1 parent cbdb296 commit 2eb310a
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 50 deletions.
14 changes: 9 additions & 5 deletions packages/lexical-editor/src/components/Editor/RichTextEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { HistoryPlugin } from "@lexical/react/LexicalHistoryPlugin";
import { ContentEditable } from "@lexical/react/LexicalContentEditable";
import { RichTextEditorProvider } from "~/context/RichTextEditorContext";
import { isValidLexicalData } from "~/utils/isValidLexicalData";
import { LexicalUpdateStatePlugin } from "~/plugins/LexicalUpdateStatePlugin";
import { UpdateStatePlugin } from "~/plugins/LexicalUpdateStatePlugin";
import { BlurEventPlugin } from "~/plugins/BlurEventPlugin/BlurEventPlugin";
import { LexicalValue, ToolbarActionPlugin } from "~/types";
import { Placeholder } from "~/ui/Placeholder";
Expand Down Expand Up @@ -113,11 +113,15 @@ const BaseRichTextEditor: React.FC<RichTextEditorProps> = ({
<Fragment key={plugin.name}>{plugin.element}</Fragment>
));

const editorValue = isValidLexicalData(value) ? value : generateInitialLexicalValue();

const initialConfig = {
editorState: isValidLexicalData(value) ? value : generateInitialLexicalValue(),
// We update the state via the `<LexicalUpdateStatePlugin/>`.
editorState: null,
namespace: "webiny",
onError: (error: Error) => {
throw error;
onError: () => {
// Ignore errors. We don't want to break the app because of errors caused by config/value updates.
// These are usually resolved in the next component render cycle.
},
nodes: [...allNodes, ...configNodes, ...(nodes || [])],
theme: { ...editorTheme.current, emotionMap: themeEmotionMap }
Expand Down Expand Up @@ -151,7 +155,7 @@ const BaseRichTextEditor: React.FC<RichTextEditorProps> = ({
>
{/* data */}
<OnChangePlugin onChange={handleOnChange} />
{value && <LexicalUpdateStatePlugin value={value} />}
<UpdateStatePlugin value={editorValue} />
<ClearEditorPlugin />
<HistoryPlugin externalHistoryState={historyState} />
{/* Events */}
Expand Down
17 changes: 10 additions & 7 deletions packages/lexical-editor/src/components/LexicalHtmlRenderer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useRef } from "react";
import { ClassNames, CSSObject } from "@emotion/react";
import { Klass, LexicalNode } from "lexical";
import { ClassNames, CSSObject } from "@emotion/react";
import { LexicalComposer } from "@lexical/react/LexicalComposer";
import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
import { ContentEditable } from "@lexical/react/LexicalContentEditable";
Expand All @@ -15,7 +15,7 @@ import {
import { isValidLexicalData } from "~/utils/isValidLexicalData";
import { generateInitialLexicalValue } from "~/utils/generateInitialLexicalValue";
import { LexicalValue } from "~/types";
import { LexicalUpdateStatePlugin } from "~/plugins/LexicalUpdateStatePlugin";
import { UpdateStatePlugin } from "~/plugins/LexicalUpdateStatePlugin";

interface LexicalHtmlRendererProps {
nodes?: Klass<LexicalNode>[];
Expand All @@ -32,20 +32,23 @@ export const BaseLexicalHtmlRenderer: React.FC<LexicalHtmlRendererProps> = ({
themeEmotionMap
}) => {
const editorTheme = useRef(createTheme());
const editorValue = isValidLexicalData(value) ? value : generateInitialLexicalValue();

const initialConfig = {
editorState: isValidLexicalData(value) ? value : generateInitialLexicalValue(),
// We update the state via the `<LexicalUpdateStatePlugin/>`.
editorState: null,
namespace: "webiny",
onError: (error: Error) => {
throw error;
onError: () => {
// Ignore errors. We don't want to break the app because of errors caused by config/value updates.
// These are usually resolved in the next component render cycle.
},
editable: false,
nodes: [...allNodes, ...(nodes || [])],
theme: { ...editorTheme.current, emotionMap: themeEmotionMap, styles: theme.styles }
};

return (
<LexicalComposer initialConfig={initialConfig}>
<LexicalComposer initialConfig={initialConfig} key={initialConfig.nodes.length}>
<RichTextPlugin
contentEditable={
<div className="editor">
Expand All @@ -55,7 +58,7 @@ export const BaseLexicalHtmlRenderer: React.FC<LexicalHtmlRendererProps> = ({
ErrorBoundary={LexicalErrorBoundary}
placeholder={null}
/>
<LexicalUpdateStatePlugin value={value} />
<UpdateStatePlugin value={editorValue} />
</LexicalComposer>
);
};
Expand Down
2 changes: 1 addition & 1 deletion packages/lexical-editor/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export { LinkPlugin } from "~/plugins/LinkPlugin/LinkPlugin";
export { FloatingLinkEditorPlugin } from "~/plugins/FloatingLinkEditorPlugin/FloatingLinkEditorPlugin";
export { CodeHighlightPlugin } from "~/plugins/CodeHighlightPlugin/CodeHighlightPlugin";
export { BlurEventPlugin } from "~/plugins/BlurEventPlugin/BlurEventPlugin";
export { LexicalUpdateStatePlugin } from "~/plugins/LexicalUpdateStatePlugin/LexicalUpdateStatePlugin";
export { UpdateStatePlugin } from "~/plugins/LexicalUpdateStatePlugin/UpdateStatePlugin";
export { FontColorPlugin } from "~/plugins/FontColorPlugin/FontColorPlugin";
export { TypographyPlugin } from "~/plugins/TypographyPlugin/TypographyPlugin";
export { QuotePlugin } from "~/plugins/WebinyQuoteNodePlugin/WebinyQuoteNodePlugin";
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useEffect } from "react";
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
import { isValidLexicalData } from "~/utils/isValidLexicalData";
import { generateInitialLexicalValue } from "~/utils/generateInitialLexicalValue";
import { LexicalValue } from "~/types";

interface UpdateStatePluginProps {
value: LexicalValue | null;
}

/**
* Updates the lexical state if new value is provided to the lexical editor trough props.
*/
export const UpdateStatePlugin = ({ value }: UpdateStatePluginProps) => {
const [editor] = useLexicalComposerContext();
useEffect(() => {
if (value && editor) {
editor.update(() => {
const editorState = editor.getEditorState();

if (JSON.stringify(editorState.toJSON()) === value) {
return;
}

try {
const initialEditorState = editor.parseEditorState(
isValidLexicalData(value)
? (value as string)
: (generateInitialLexicalValue() as string)
);
editor.setEditorState(initialEditorState);
} catch (err) {
console.log("Lexical state update error", err.message);
// Ignore errors
}
});
}
}, [value, editor]);

return null;
};
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from "./LexicalUpdateStatePlugin";
export * from "./UpdateStatePlugin";

0 comments on commit 2eb310a

Please sign in to comment.