From db0f7729c58eee8656495a131790a0244e9c0d1f Mon Sep 17 00:00:00 2001 From: JOOHOJANG Date: Mon, 28 Oct 2024 23:16:13 +0900 Subject: [PATCH] Add throttle to prevent preview's indiscriminate updates --- frontend/src/components/editor/Preview.tsx | 34 +++++++++++++++------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/frontend/src/components/editor/Preview.tsx b/frontend/src/components/editor/Preview.tsx index f5de285a..b44550e5 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"; @@ -18,6 +17,10 @@ import markdownItSanitizer from "markdown-it-sanitizer"; 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, @@ -46,27 +49,36 @@ const Preview = () => { const editorStore = useSelector(selectEditor); const [content, setContent] = useState(""); const containerRef = useRef(null); + const throttledUpdatePreviewConetent = useMemo( + () => + _.throttle( + () => { + const editorText = 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] + ); useEffect(() => { if (!editorStore.doc) return; - const updatePreviewContent = () => { - const editorText = editorStore.doc?.getRoot().content?.toString() || ""; - // Add soft line break - setContent(addSoftLineBreak(editorText)); - }; - - updatePreviewContent(); + throttledUpdatePreviewConetent(); const unsubscribe = editorStore.doc.subscribe("$.content", () => { - updatePreviewContent(); + throttledUpdatePreviewConetent(); }); return () => { unsubscribe(); setContent(""); }; - }, [editorStore.doc]); + }, [editorStore.doc, throttledUpdatePreviewConetent]); useEffect(() => { if (containerRef.current == null) {