Skip to content

Commit 676357e

Browse files
committed
fix: fixed regression
1 parent 89edd87 commit 676357e

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

packages/react-dsfr-tiptap/src/components/Provider.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { fr } from "@codegouvfr/react-dsfr";
22
import { useEditor, UseEditorOptions } from "@tiptap/react";
3-
import { ReactNode } from "react";
3+
import { ReactNode, useEffect } from "react";
44
import { tss } from "tss-react";
55

66
import { editorContext } from "../contexts/editor";
@@ -14,6 +14,28 @@ function Provider(props: IProviderProps) {
1414
const editor = useEditor(rest);
1515
const { classes } = useStyles();
1616

17+
// Keep the TipTap editor content in sync when the `content` prop changes.
18+
// TipTap only uses `content` at initialization; updates require an explicit command.
19+
useEffect(() => {
20+
if (!editor) return;
21+
const next = props.content;
22+
if (typeof next !== "string") return;
23+
const ct = props.contentType;
24+
// Determine current content based on contentType (markdown/html)
25+
type MaybeMarkdownEditor = typeof editor & { getMarkdown?: () => string };
26+
const mdEditor = editor as MaybeMarkdownEditor;
27+
const current = ct === "markdown" && typeof mdEditor.getMarkdown === "function" ? mdEditor.getMarkdown() : editor.getHTML();
28+
if (current !== next) {
29+
// Update without emitting an update event to avoid feedback loops.
30+
const commands = editor.commands as unknown as { setMarkdown?: (md: string, opts?: { emitUpdate?: boolean }) => void };
31+
if (ct === "markdown" && typeof commands.setMarkdown === "function") {
32+
commands.setMarkdown(next, { emitUpdate: false });
33+
} else {
34+
editor.commands.setContent(next, { emitUpdate: false });
35+
}
36+
}
37+
}, [editor, props.content, props.contentType]);
38+
1739
return (
1840
<div className={classes.root}>
1941
<editorContext.Provider value={editor}>{children}</editorContext.Provider>

packages/react-dsfr-tiptap/src/components/RichTextEditor.test.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,15 @@ describe("RichTextEditor component", () => {
1212
expect(title).toBeInTheDocument();
1313
expect(title instanceof HTMLHeadingElement).toBe(true);
1414
});
15+
16+
test("updates editor when content prop changes", async () => {
17+
const { rerender } = render(<RichTextEditor content="<p>First</p>" />);
18+
await waitFor(() => expect(screen.queryAllByRole("button").length).toBeGreaterThan(0));
19+
expect(screen.getByText("First")).toBeInTheDocument();
20+
21+
// Change content prop simulating a reset
22+
rerender(<RichTextEditor content="<h2>Second</h2>" />);
23+
// The new heading should appear, old text should be gone
24+
await waitFor(() => expect(screen.getByText("Second")).toBeInTheDocument());
25+
});
1526
});

0 commit comments

Comments
 (0)