1
0
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:
Ulion
2021-04-01 09:24:07 +08:00
committed by GitHub
parent 7a9b4c5787
commit 39e47dc518
4 changed files with 546 additions and 535 deletions

View File

@@ -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.

View File

@@ -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 &&

View File

@@ -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}

View 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)
}