What I need to get done
I want to make a simple controlled lexical plaintex editor - one which is controlled by a parent string field.
But I'm really struggling with getting my editor to simultaneously:
- Be adopting parent state whenever it changes
- Retain
Selection
after adopting parent state - Not automatically focus just because the external value changed (and got adopted)
Where I got so far
I tried a couple things, but this is the closest I got - Sandbox here:
export const useAdoptPlaintextValue = (value: string) => {
const [editor] = useLexicalComposerContext();
useEffect(() => {
editor.update(() => {
const initialSelection = $getSelection()?.clone() ?? null;
$getRoot().clear();
$getRoot().select(); // for some reason this is not even necessary
$getSelection()?.insertText(value);
$setSelection(initialSelection);
});
}, [value, editor]);
};
This approach works well when writing into the input itself, but the imperative adoption of value
only works until the input was first selected. After it has already been selected (even when un-selected again), editor only adopts the value for one "render frame" and then immediately re-renders with the old value.
I'm clearly doing something wrong with selection, because:
- removing
setSelection(initialSelection)
also removes this problem - but then selection doesn't get maintained between updates, which is also unacceptable. - I'm getting this error on every keystroke:
updateEditor: selection has been lost because the previously selected nodes have been removed and selection wasn't moved to another node. Ensure selection changes after removing/replacing a selected node.
... It seems to me that initialSelection
retains a reference to nodes that are deleted by $getRoot().clear()
, but I tried working my way around it and got nowhere.
I'll be glad for any advice/help about my code or towards my goal.
Thank you 🙏
$getRoot().getTextContent() === value
) - this way reconcilliation never gets triggered and the input works just as I want it! – Moulmein