mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-06 23:36:31 +02:00
Use callback-style ref in Element
component (#5105)
* Use callback-style ref in Element component * Add changeset
This commit is contained in:
5
.changeset/poor-jokes-chew.md
Normal file
5
.changeset/poor-jokes-chew.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'slate-react': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Change `Element` component to use callback-style ref to reliably track DOM node of rendered custom elements
|
@@ -1,11 +1,10 @@
|
|||||||
import React, { Fragment, useRef } from 'react'
|
import React, { useCallback } from 'react'
|
||||||
import getDirection from 'direction'
|
import getDirection from 'direction'
|
||||||
import { Editor, Node, Range, Element as SlateElement } from 'slate'
|
import { Editor, Node, Range, Element as SlateElement } from 'slate'
|
||||||
|
|
||||||
import Text from './text'
|
import Text from './text'
|
||||||
import useChildren from '../hooks/use-children'
|
import useChildren from '../hooks/use-children'
|
||||||
import { ReactEditor, useSlateStatic, useReadOnly } from '..'
|
import { ReactEditor, useSlateStatic, useReadOnly } from '..'
|
||||||
import { useIsomorphicLayoutEffect } from '../hooks/use-isomorphic-layout-effect'
|
|
||||||
import {
|
import {
|
||||||
NODE_TO_ELEMENT,
|
NODE_TO_ELEMENT,
|
||||||
ELEMENT_TO_NODE,
|
ELEMENT_TO_NODE,
|
||||||
@@ -19,7 +18,6 @@ import {
|
|||||||
RenderLeafProps,
|
RenderLeafProps,
|
||||||
RenderPlaceholderProps,
|
RenderPlaceholderProps,
|
||||||
} from './editable'
|
} from './editable'
|
||||||
import { IS_ANDROID } from '../utils/environment'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Element.
|
* Element.
|
||||||
@@ -41,11 +39,25 @@ const Element = (props: {
|
|||||||
renderLeaf,
|
renderLeaf,
|
||||||
selection,
|
selection,
|
||||||
} = props
|
} = props
|
||||||
const ref = useRef<HTMLElement>(null)
|
|
||||||
const editor = useSlateStatic()
|
const editor = useSlateStatic()
|
||||||
const readOnly = useReadOnly()
|
const readOnly = useReadOnly()
|
||||||
const isInline = editor.isInline(element)
|
const isInline = editor.isInline(element)
|
||||||
const key = ReactEditor.findKey(editor, element)
|
const key = ReactEditor.findKey(editor, element)
|
||||||
|
const ref = useCallback(
|
||||||
|
(ref: HTMLElement | null) => {
|
||||||
|
// Update element-related weak maps with the DOM element ref.
|
||||||
|
const KEY_TO_ELEMENT = EDITOR_TO_KEY_TO_ELEMENT.get(editor)
|
||||||
|
if (ref) {
|
||||||
|
KEY_TO_ELEMENT?.set(key, ref)
|
||||||
|
NODE_TO_ELEMENT.set(element, ref)
|
||||||
|
ELEMENT_TO_NODE.set(ref, element)
|
||||||
|
} else {
|
||||||
|
KEY_TO_ELEMENT?.delete(key)
|
||||||
|
NODE_TO_ELEMENT.delete(element)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[editor, key, element]
|
||||||
|
)
|
||||||
let children: React.ReactNode = useChildren({
|
let children: React.ReactNode = useChildren({
|
||||||
decorations,
|
decorations,
|
||||||
node: element,
|
node: element,
|
||||||
@@ -119,19 +131,6 @@ const Element = (props: {
|
|||||||
NODE_TO_PARENT.set(text, element)
|
NODE_TO_PARENT.set(text, element)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update element-related weak maps with the DOM element ref.
|
|
||||||
useIsomorphicLayoutEffect(() => {
|
|
||||||
const KEY_TO_ELEMENT = EDITOR_TO_KEY_TO_ELEMENT.get(editor)
|
|
||||||
if (ref.current) {
|
|
||||||
KEY_TO_ELEMENT?.set(key, ref.current)
|
|
||||||
NODE_TO_ELEMENT.set(element, ref.current)
|
|
||||||
ELEMENT_TO_NODE.set(ref.current, element)
|
|
||||||
} else {
|
|
||||||
KEY_TO_ELEMENT?.delete(key)
|
|
||||||
NODE_TO_ELEMENT.delete(element)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return renderElement({ attributes, children, element })
|
return renderElement({ attributes, children, element })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user