From da46422764366a14ccd2d458d3572d2d7b02a612 Mon Sep 17 00:00:00 2001 From: Max Leiter Date: Mon, 21 Mar 2022 22:50:25 -0700 Subject: [PATCH] client: stop some unncessary re-renders on new page --- client/components/document-list/index.tsx | 34 ++ client/components/document/index.tsx | 27 +- .../drag-and-drop/drag-and-drop.module.css | 4 - client/components/new-post/index.tsx | 51 ++- client/components/new-post/title/index.tsx | 9 +- .../preview/react-markdown-preview.tsx | 4 +- client/package.json | 9 +- client/styles/globals.css | 4 + client/yarn.lock | 324 +++--------------- 9 files changed, 133 insertions(+), 333 deletions(-) create mode 100644 client/components/document-list/index.tsx diff --git a/client/components/document-list/index.tsx b/client/components/document-list/index.tsx new file mode 100644 index 00000000..7ad88007 --- /dev/null +++ b/client/components/document-list/index.tsx @@ -0,0 +1,34 @@ +import type { Document } from "@lib/types" +import DocumentComponent from "@components/document" +import { ChangeEvent, memo, useCallback } from "react" + +const DocumentList = ({ docs, removeDoc, updateDocContent, updateDocTitle }: { + docs: Document[], + updateDocTitle: (i: number) => (title: string) => void + updateDocContent: (i: number) => (content: string) => void + removeDoc: (i: number) => () => void +}) => { + const handleOnChange = useCallback((i) => (e: ChangeEvent) => { + updateDocContent(i)(e.target.value) + }, [updateDocContent]) + + return (<>{ + docs.map(({ content, id, title }, i) => { + return ( + + ) + }) + } + ) +} + +export default memo(DocumentList) diff --git a/client/components/document/index.tsx b/client/components/document/index.tsx index f77b0b8f..b34f1b19 100644 --- a/client/components/document/index.tsx +++ b/client/components/document/index.tsx @@ -27,6 +27,7 @@ type Props = { content?: string setTitle?: (title: string) => void setContent?: (content: string) => void + handleOnContentChange?: (e: ChangeEvent) => void initialTab?: "edit" | "preview" skeleton?: boolean id?: string @@ -60,7 +61,7 @@ const DownloadButton = ({ rawLink }: { rawLink?: string }) => { } -const Document = ({ remove, editable, title, content, setTitle, setContent, initialTab = 'edit', skeleton, id }: Props) => { +const Document = ({ remove, editable, title, content, setTitle, setContent, initialTab = 'edit', skeleton, id, handleOnContentChange }: Props) => { const codeEditorRef = useRef(null) const [tab, setTab] = useState(initialTab) // const height = editable ? "500px" : '100%' @@ -73,14 +74,16 @@ const Document = ({ remove, editable, title, content, setTitle, setContent, init setTab(newTab as 'edit' | 'preview') } - const getType = useMemo(() => { + const getType = useCallback(() => { if (!title) return const pathParts = title.split(".") const language = pathParts.length > 1 ? pathParts[pathParts.length - 1] : "" return language }, [title]) - const removeFile = (remove?: () => void) => { + const onTitleChange = useCallback((event: ChangeEvent) => setTitle ? setTitle(event.target.value) : null, [setTitle]) + + const removeFile = useCallback(() => (remove?: () => void) => { if (remove) { if (content && content.trim().length > 0) { const confirmed = window.confirm("Are you sure you want to remove this file?") @@ -91,13 +94,13 @@ const Document = ({ remove, editable, title, content, setTitle, setContent, init remove() } } - } + }, [content]) - const rawLink = useMemo(() => { + const rawLink = () => { if (id) { return `/file/raw/${id}` } - }, [id]) + } if (skeleton) { return <> @@ -114,6 +117,8 @@ const Document = ({ remove, editable, title, content, setTitle, setContent, init } + + return ( <> @@ -122,7 +127,7 @@ const Document = ({ remove, editable, title, content, setTitle, setContent, init ) => setTitle ? setTitle(event.target.value) : null} + onChange={onTitleChange} marginTop="var(--gap-double)" size={1.2} font={1.2} @@ -131,11 +136,11 @@ const Document = ({ remove, editable, title, content, setTitle, setContent, init width={"100%"} id={title} /> - {remove && editable &&