I am using this code to create a basic Prose Mirror rich text editor in my React Application. In this code example I do not have any thing in the useEffect dependency list. When I do add state
which it requires (notifying me through VSC intellisense), the editor state starts refreshing on every 2-3 seconds and every change in content. Like literally just clicking on the editor text box causes the dispatchTransaction to fire. And that runs the entire useEffect again.
Whats the best way to handle this issue? Should I not use useEffect? but then I will not be able to run the view.destroy();
on dismount.
Here is my code:
"use client";
import { history } from "prosemirror-history";
import { DOMParser, DOMSerializer } from "prosemirror-model";
import { EditorState } from "prosemirror-state";
import { EditorView } from "prosemirror-view";
import { useEffect, useRef } from "react";
import { buildKeymap } from "./ProseMirrorKeymap";
import { singleLineRichTextSchema } from "./ProseMirrorSchema";
const ProseMirrorTextEditor: React.FC<{
content: string;
singleLine: boolean;
richText?: boolean;
updateContent: (content: string) => void;
}> = ({ content, updateContent, singleLine = true, richText = false }) => {
const prosemirrorEditorRef = useRef<HTMLDivElement>(null);
let schema = singleLineRichTextSchema;
const pmDoc = document.implementation.createHTMLDocument();
pmDoc.body.innerHTML = content;
// Parse the content using the DOMParser from ProseMirror
const doc = DOMParser.fromSchema(schema).parse(pmDoc.body);
useEffect(() => {
// Initialize the editor state with the document
let state = EditorState.create({
doc,
plugins: [history(), buildKeymap()], // Add basic keymap for editing
});
// Set up the editor view
let view = new EditorView(prosemirrorEditorRef.current, {
state,
dispatchTransaction(transaction) {
const newState = view.state.apply(transaction);
view.updateState(newState);
if (transaction.docChanged) {
const fragment = DOMSerializer.fromSchema(
newState.schema
).serializeFragment(newState.doc.content);
const node = document.createElement("div");
node.append(fragment);
updateContent(node.innerHTML);
}
},
});
// Cleanup function to destroy the editor view
return () => view.destroy();
}, []);
return (
<div ref={prosemirrorEditorRef} id="content"></div>
);
};
export default ProseMirrorTextEditor;