mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-15 03:33:59 +02:00
Decorate re-render optimize to not re-render all elements. (#4138)
* Decorate re-render optimize to not re-render all elements. * Move provider one level up due to Children no longer component. * lint fix
This commit is contained in:
@@ -27,6 +27,7 @@ import { ReactEditor } from '..'
|
|||||||
import { ReadOnlyContext } from '../hooks/use-read-only'
|
import { ReadOnlyContext } from '../hooks/use-read-only'
|
||||||
import { useSlate } from '../hooks/use-slate'
|
import { useSlate } from '../hooks/use-slate'
|
||||||
import { useIsomorphicLayoutEffect } from '../hooks/use-isomorphic-layout-effect'
|
import { useIsomorphicLayoutEffect } from '../hooks/use-isomorphic-layout-effect'
|
||||||
|
import { DecorateContext } from '../hooks/use-decorate'
|
||||||
import {
|
import {
|
||||||
DOMElement,
|
DOMElement,
|
||||||
DOMNode,
|
DOMNode,
|
||||||
@@ -497,6 +498,7 @@ export const Editable = (props: EditableProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ReadOnlyContext.Provider value={readOnly}>
|
<ReadOnlyContext.Provider value={readOnly}>
|
||||||
|
<DecorateContext.Provider value={decorate}>
|
||||||
<Component
|
<Component
|
||||||
// COMPAT: The Grammarly Chrome extension works by changing the DOM
|
// COMPAT: The Grammarly Chrome extension works by changing the DOM
|
||||||
// out from under `contenteditable` elements, which leads to weird
|
// out from under `contenteditable` elements, which leads to weird
|
||||||
@@ -507,7 +509,9 @@ export const Editable = (props: EditableProps) => {
|
|||||||
// COMPAT: Certain browsers don't support the `beforeinput` event, so we'd
|
// COMPAT: Certain browsers don't support the `beforeinput` event, so we'd
|
||||||
// have to use hacks to make these replacement-based features work.
|
// have to use hacks to make these replacement-based features work.
|
||||||
spellCheck={!HAS_BEFORE_INPUT_SUPPORT ? false : attributes.spellCheck}
|
spellCheck={!HAS_BEFORE_INPUT_SUPPORT ? false : attributes.spellCheck}
|
||||||
autoCorrect={!HAS_BEFORE_INPUT_SUPPORT ? false : attributes.autoCorrect}
|
autoCorrect={
|
||||||
|
!HAS_BEFORE_INPUT_SUPPORT ? false : attributes.autoCorrect
|
||||||
|
}
|
||||||
autoCapitalize={
|
autoCapitalize={
|
||||||
!HAS_BEFORE_INPUT_SUPPORT ? false : attributes.autoCapitalize
|
!HAS_BEFORE_INPUT_SUPPORT ? false : attributes.autoCapitalize
|
||||||
}
|
}
|
||||||
@@ -1039,7 +1043,6 @@ export const Editable = (props: EditableProps) => {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{useChildren({
|
{useChildren({
|
||||||
decorate,
|
|
||||||
decorations,
|
decorations,
|
||||||
node: editor,
|
node: editor,
|
||||||
renderElement,
|
renderElement,
|
||||||
@@ -1047,6 +1050,7 @@ export const Editable = (props: EditableProps) => {
|
|||||||
selection: editor.selection,
|
selection: editor.selection,
|
||||||
})}
|
})}
|
||||||
</Component>
|
</Component>
|
||||||
|
</DecorateContext.Provider>
|
||||||
</ReadOnlyContext.Provider>
|
</ReadOnlyContext.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1055,7 +1059,7 @@ export const Editable = (props: EditableProps) => {
|
|||||||
* A default memoized decorate function.
|
* A default memoized decorate function.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const defaultDecorate = () => []
|
const defaultDecorate: (entry: NodeEntry) => Range[] = () => []
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if two DOM range objects are equal.
|
* Check if two DOM range objects are equal.
|
||||||
|
@@ -22,7 +22,6 @@ import { RenderElementProps, RenderLeafProps } from './editable'
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const Element = (props: {
|
const Element = (props: {
|
||||||
decorate: (entry: NodeEntry) => Range[]
|
|
||||||
decorations: Range[]
|
decorations: Range[]
|
||||||
element: SlateElement
|
element: SlateElement
|
||||||
renderElement?: (props: RenderElementProps) => JSX.Element
|
renderElement?: (props: RenderElementProps) => JSX.Element
|
||||||
@@ -30,7 +29,6 @@ const Element = (props: {
|
|||||||
selection: Range | null
|
selection: Range | null
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
decorate,
|
|
||||||
decorations,
|
decorations,
|
||||||
element,
|
element,
|
||||||
renderElement = (p: RenderElementProps) => <DefaultElement {...p} />,
|
renderElement = (p: RenderElementProps) => <DefaultElement {...p} />,
|
||||||
@@ -44,7 +42,6 @@ const Element = (props: {
|
|||||||
const key = ReactEditor.findKey(editor, element)
|
const key = ReactEditor.findKey(editor, element)
|
||||||
|
|
||||||
let children: JSX.Element | null = useChildren({
|
let children: JSX.Element | null = useChildren({
|
||||||
decorate,
|
|
||||||
decorations,
|
decorations,
|
||||||
node: element,
|
node: element,
|
||||||
renderElement,
|
renderElement,
|
||||||
@@ -131,7 +128,6 @@ const Element = (props: {
|
|||||||
|
|
||||||
const MemoizedElement = React.memo(Element, (prev, next) => {
|
const MemoizedElement = React.memo(Element, (prev, next) => {
|
||||||
return (
|
return (
|
||||||
prev.decorate === next.decorate &&
|
|
||||||
prev.element === next.element &&
|
prev.element === next.element &&
|
||||||
prev.renderElement === next.renderElement &&
|
prev.renderElement === next.renderElement &&
|
||||||
prev.renderLeaf === next.renderLeaf &&
|
prev.renderLeaf === next.renderLeaf &&
|
||||||
|
@@ -5,6 +5,7 @@ import ElementComponent from '../components/element'
|
|||||||
import TextComponent from '../components/text'
|
import TextComponent from '../components/text'
|
||||||
import { ReactEditor } from '..'
|
import { ReactEditor } from '..'
|
||||||
import { useSlateStatic } from './use-slate-static'
|
import { useSlateStatic } from './use-slate-static'
|
||||||
|
import { useDecorate } from './use-decorate'
|
||||||
import { NODE_TO_INDEX, NODE_TO_PARENT } from '../utils/weak-maps'
|
import { NODE_TO_INDEX, NODE_TO_PARENT } from '../utils/weak-maps'
|
||||||
import { RenderElementProps, RenderLeafProps } from '../components/editable'
|
import { RenderElementProps, RenderLeafProps } from '../components/editable'
|
||||||
|
|
||||||
@@ -13,21 +14,14 @@ import { RenderElementProps, RenderLeafProps } from '../components/editable'
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const useChildren = (props: {
|
const useChildren = (props: {
|
||||||
decorate: (entry: NodeEntry) => Range[]
|
|
||||||
decorations: Range[]
|
decorations: Range[]
|
||||||
node: Ancestor
|
node: Ancestor
|
||||||
renderElement?: (props: RenderElementProps) => JSX.Element
|
renderElement?: (props: RenderElementProps) => JSX.Element
|
||||||
renderLeaf?: (props: RenderLeafProps) => JSX.Element
|
renderLeaf?: (props: RenderLeafProps) => JSX.Element
|
||||||
selection: Range | null
|
selection: Range | null
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const { decorations, node, renderElement, renderLeaf, selection } = props
|
||||||
decorate,
|
const decorate = useDecorate()
|
||||||
decorations,
|
|
||||||
node,
|
|
||||||
renderElement,
|
|
||||||
renderLeaf,
|
|
||||||
selection,
|
|
||||||
} = props
|
|
||||||
const editor = useSlateStatic()
|
const editor = useSlateStatic()
|
||||||
const path = ReactEditor.findPath(editor, node)
|
const path = ReactEditor.findPath(editor, node)
|
||||||
const children = []
|
const children = []
|
||||||
@@ -55,7 +49,6 @@ const useChildren = (props: {
|
|||||||
if (Element.isElement(n)) {
|
if (Element.isElement(n)) {
|
||||||
children.push(
|
children.push(
|
||||||
<ElementComponent
|
<ElementComponent
|
||||||
decorate={decorate}
|
|
||||||
decorations={ds}
|
decorations={ds}
|
||||||
element={n}
|
element={n}
|
||||||
key={key.id}
|
key={key.id}
|
||||||
|
18
packages/slate-react/src/hooks/use-decorate.ts
Normal file
18
packages/slate-react/src/hooks/use-decorate.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { createContext, useContext } from 'react'
|
||||||
|
import { Range, NodeEntry } from 'slate'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A React context for sharing the `decorate` prop of the editable.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const DecorateContext = createContext<(entry: NodeEntry) => Range[]>(
|
||||||
|
() => []
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current `decorate` prop of the editable.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const useDecorate = (): ((entry: NodeEntry) => Range[]) => {
|
||||||
|
return useContext(DecorateContext)
|
||||||
|
}
|
Reference in New Issue
Block a user