#9111·lexical

Feature: Implement lint rule about using node variable in update closure

Author: levenstaCreated Sep 1, 2026Updated Sep 1, 2026
Labelsenhancement

Description

In some cases, a variable within an update may be closed with a node, especially in the context of React. A contrived example:

javascript
const [sourceNode, setSourceNode] = useState<LexicalNode | null>(null)
const [editor] = useLexicalComposerContext();

const handleClick() => {
  if (!sourceNode) return;
  editor.update(() => {
    sourceNode.selectEnd();
  });
}

The pitfall of this code is that, despite checking for the presence of the sourceNode, it may be missing from the LexicalState for some reason during an update. The correct pattern would be to check via the isAttached() method

diff
-  if (!sourceNode) return;
+  if (!sourceNode || !sourceNode.isAttached()) return;

or to store the key and check via $getNodeByKey

diff
-const [sourceNode, setSourceNode] = useState<LexicalNode | null>(null)
+const [sourceNodeKey, setSourceNodeKey] = useState<NodeKey>()
const [editor] = useLexicalComposerContext();

const handleClick() => {
+ const sourceNode = $getNodeByKey(sourceNodeKey);
  if (!sourceNode) return;
  editor.update(() => {
    sourceNode.selectEnd();
  });
}

Otherwise, if the node is detached from the state, the exception will be thrown:

Lexical node does not exist in active editor state.
Avoid using the same node references between nested closures from editorState.read/editor.update.

Impact

A lint rule would prevent such potential errors and allow for safer code handling of state. A similar error can occur not only during updating, but also during reading of state