From 213edbbf3abc407532aeda72e40d6f01d368c33c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claud=C3=A9ric=20Demers?= Date: Fri, 24 Feb 2023 16:40:28 -0500 Subject: [PATCH] Version Packages (#5290) (#5306) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] --- .changeset/text-leaf-memoization.md | 5 ++++ .../slate-react/src/components/string.tsx | 24 +++++++++---------- 2 files changed, 17 insertions(+), 12 deletions(-) create mode 100644 .changeset/text-leaf-memoization.md diff --git a/.changeset/text-leaf-memoization.md b/.changeset/text-leaf-memoization.md new file mode 100644 index 000000000..73eb3aa3a --- /dev/null +++ b/.changeset/text-leaf-memoization.md @@ -0,0 +1,5 @@ +--- +'slate-react': patch +--- + +Use memoization to avoid unnecessary `textContent` updates in `` component. diff --git a/packages/slate-react/src/components/string.tsx b/packages/slate-react/src/components/string.tsx index b66de3791..1f7fde588 100644 --- a/packages/slate-react/src/components/string.tsx +++ b/packages/slate-react/src/components/string.tsx @@ -1,4 +1,4 @@ -import React, { useRef } from 'react' +import React, { forwardRef, memo, useRef, useState } from 'react' import { Editor, Text, Path, Element, Node } from 'slate' import { ReactEditor, useSlateStatic } from '..' @@ -61,12 +61,11 @@ const String = (props: { */ const TextString = (props: { text: string; isTrailing?: boolean }) => { const { text, isTrailing = false } = props - const ref = useRef(null) - const getTextContent = () => { return `${text ?? ''}${isTrailing ? '\n' : ''}` } + const [initialText] = useState(getTextContent) // This is the actual text rendering boundary where we interface with the DOM // The text is not rendered as part of the virtual DOM, as since we handle basic character insertions natively, @@ -89,19 +88,20 @@ const TextString = (props: { text: string; isTrailing?: boolean }) => { // as this effectively replaces "specifying the text in the virtual DOM under the below" on each render }) - // Render text content immediately if it's the first-time render - // Ensure that text content is rendered on server-side rendering - if (!ref.current) { + // We intentionally render a memoized that only receives the initial text content when the component is mounted. + // We defer to the layout effect above to update the `textContent` of the span element when needed. + return {initialText} +} + +const MemoizedText = memo( + forwardRef((props, ref) => { return ( - {getTextContent()} + {props.children} ) - } - - // the span is intentionally same on every render in virtual DOM, actual rendering happens in the layout effect above - return -} + }) +) /** * Leaf strings without text, render as zero-width strings.