From ecc00dcaa7c237f6152d4549a71fa9c1e67f762a Mon Sep 17 00:00:00 2001 From: JOOHOJANG <46807540+JOOHOJANG@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:20:29 +0900 Subject: [PATCH] Add `throttle` to prevent preview's indiscriminate updates (#391) * Add throttle to prevent preview's indiscriminate updates * Update preview text from cmview * Add cmview into useMemo dependencies * Fix typo --- frontend/src/components/editor/Preview.tsx | 37 +++++++++++++++------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/frontend/src/components/editor/Preview.tsx b/frontend/src/components/editor/Preview.tsx index 5b59f634..fc92c807 100644 --- a/frontend/src/components/editor/Preview.tsx +++ b/frontend/src/components/editor/Preview.tsx @@ -1,10 +1,9 @@ import { CircularProgress, Stack } from "@mui/material"; import "katex/dist/katex.min.css"; -import { useEffect, useRef, useState } from "react"; +import { useEffect, useRef, useState, useMemo } from "react"; import { useSelector } from "react-redux"; import { useCurrentTheme } from "../../hooks/useCurrentTheme"; import { selectEditor } from "../../store/editorSlice"; -import { addSoftLineBreak } from "../../utils/document"; import MarkdownIt from "markdown-it"; import { toHtml } from "hast-util-to-html"; import markdownItKatex from "@vscode/markdown-it-katex"; @@ -15,6 +14,10 @@ import markdownItTaskCheckbox from "markdown-it-task-checkbox"; import * as IncrementalDOM from "incremental-dom"; import "./editor.css"; import "./preview.css"; +import _ from "lodash"; +import { addSoftLineBreak } from "../../utils/document"; + +const DELAY = 500; const md = new MarkdownIt({ html: true, @@ -44,27 +47,39 @@ const Preview = () => { const editorStore = useSelector(selectEditor); const [content, setContent] = useState(""); const containerRef = useRef(null); + const throttledUpdatePreviewContent = useMemo( + () => + _.throttle( + () => { + const editorText = + editorStore.cmView?.state.doc.toString() || + editorStore.doc?.getRoot().content?.toString() || + ""; + + // Add soft line break + setContent(addSoftLineBreak(editorText)); + }, + DELAY, + // Set trailing true to prevent ignoring last call + { trailing: true } + ), + [editorStore.doc, editorStore.cmView] + ); useEffect(() => { if (!editorStore.doc) return; - const updatePreviewContent = () => { - const editorText = editorStore.doc?.getRoot().content?.toString() || ""; - // Add soft line break - setContent(addSoftLineBreak(editorText)); - }; - - updatePreviewContent(); + throttledUpdatePreviewContent(); const unsubscribe = editorStore.doc.subscribe("$.content", () => { - updatePreviewContent(); + throttledUpdatePreviewContent(); }); return () => { unsubscribe(); setContent(""); }; - }, [editorStore.doc]); + }, [editorStore.doc, throttledUpdatePreviewContent]); useEffect(() => { if (containerRef.current == null) {