Explain a quirk with reference to node objects
See original GitHub issueDo you want to request a feature or report a bug?
feature
What’s the current behavior?
Slate treats the node
as a unique object reference. This is evident by the use of WeakMap<Node, *>
, where the node
object reference is used as the identifier.
But nothing prevents me from inserting the same node multiple times. Here’s how easy it is to make the mistake. A diff of editable-voids.js
example:
diff --git a/site/examples/editable-voids.js b/site/examples/editable-voids.js
index c2187cc9..8a871a8b 100644
--- a/site/examples/editable-voids.js
+++ b/site/examples/editable-voids.js
@@ -7,6 +7,8 @@ import { css } from 'emotion'
import RichTextEditor from './richtext'
import { Button, Icon, Toolbar } from '../components'
+const VOID_NODE = { type: 'editable-void', children: [{ text: '' }] }
+
const EditableVoidsExample = () => {
const [value, setValue] = useState(initialValue)
const editor = useMemo(
@@ -39,9 +41,7 @@ const withEditableVoids = editor => {
}
const insertEditableVoid = editor => {
- const text = { text: '' }
- const voidNode = { type: 'editable-void', children: [text] }
- Transforms.insertNodes(editor, voidNode)
+ Transforms.insertNodes(editor, VOID_NODE)
}
const Element = props => {
The voidNode
is the same every time, so it’s not by any stretch of the imagination that someone might see and be “Oh, I can extract that as a constant instead.”, and produce code similar to the diff above.
I’m saying that because it’s almost exactly what I did in our codebase.
What follows is after inserting multiple of these nodes, you’ll see “Encountered two children with the same key” warning. This is not that terrible, but the same problems ensue with every bit of logic which relies on the node
object reference being unique.
Slate: 0.58.4 (but probably applies to any version after 0.50’s migration to native objects) Browser: Chrome / Safari / Firefox / Edge OS: Mac / Windows / Linux / iOS / Android
What’s the expected behavior?
It would be nice to have some kind of warning when inserting a duplicate node reference.
But for starters, it would be ok to explain this quirk in the docs.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:3
- Comments:5 (4 by maintainers)
There are areas of Slate where the node is copied in the insertion vs. passed in directly. Also, Slate uses Immer under the hood when applying ops so I’m not sure if what you are doing is actually keeping the object reference in
editor.children
in multiple places. Have you actually validated that it’s the same object (e.g., by using===
on the same node extracted fromeditor.children
)? I would be interested to know if Immer does something under the hood that makes it not the same object reference…@BrentFarese I have tested it, and yes, it’s the exact same node.
Steps:
Go to
/examples/editable-voids
and press the add button twice, to add 2 more editable voids nodes (callsinsertEditableVoid
twice).The second time, the
console.log
outputs[0, 1, 2, 3, 3]
. This confirms it’s the exact same node object.https://github.com/ianstormtaylor/slate/blob/1cf63f0a19a45c3b35ea3f8682e57a28cacfb4d1/packages/slate/src/interfaces/editor.ts#L1255-L1258
There is no sign of immer when working with the
node
to insert. The code takesop.node
and throws it in theeditor.children
, without creating a copy of the object.