React FAQ
My app does not work in dev when using StrictMode, help!?
When hooks are used correctly, there are no known issues with React StrictMode
and Lexical. The first thing you should do is go through React's documentation
to make sure that your usage of useEffect
and other hooks follow React's
conventions and guidelines. This is a great place to start:
My Effect runs twice when the component mounts
Some Lexical-specific concerns (which are consequences of React's concurrent and StrictMode semantics, not due to anything unusual in Lexical):
- In React 19,
useMemo
calls are cached across StrictMode re-renders, so only one editor will be used for both renders. If you have auseEffect
call with side-effects (such as updating the document when a plug-in initializes), then you should first check to make sure that this effect has not already occurred (e.g. by checking the state of the document or undoing the change as a cleanup function returned by the effect) LexicalComposer
's initialConfig prop is only considered once during the first render (useMemo
is used to create theLexicalComposerContext
which includes the editor and theme)- If you are using an
editorState
argument in the config when creating the editor, it will only be called once when the editor is created. - You should generally prefer to use hooks that return state such as
useLexicalEditable
(useLexicalSubscription
is a generalization of this style) rather than manually registering the listeners and expecting a particular sequence of triggers to be called, especially when their source is an effect. Listeners are only called when state changes, and in StrictMode the state may have changed during the initial render. The listeners registered from your second render will not be called if the change was triggered by the first render, and you will likely not see the listeners triggered during the first render because those effects were immediately cleaned up before the change effect occurred.
LexicalComposerContext.useLexicalComposerContext: cannot find a LexicalComposerContext
This error happens for one reason: the useLexicalComposerContext()
hook
was called from a component that is not a child of a LexicalComposer
,
LexicalNestedComposer
, or LexicalComposerContext.Provider
from the same
build of Lexical that the hook was imported from.
The most common root causes of this issue are:
- You are trying to use
useLexicalComposerContext()
in a component that is not a child of theLexicalComposer
. If you need to do that, you need to pass the context or editor up the tree with something likeEditorRefPlugin
. - You have multiple builds of Lexical in your project. This could be because
you have a dependency that has a direct dependency on some other version
of Lexical (these packages should have Lexical as
peerDependencies
, but not all do), or because your project mixes import and require statements to import Lexical (including both the esm and cjs builds of the same version of Lexical). Resolving this generally requires overriding what your package manager does inpackage.json
, and/or what the bundler does in some configuration file for your framework or bundler. There are a lot of combinations of tools in the ecosystem (npm, pnpm, yarn, webpack, vite, next.js, etc.), so the syntax of that workaround is quite dependent on precisely which tools (and even versions of those tools) that your project is using.
Other complications when using dev mode with fast refresh (aka hot module replacement)
Depending on precisely how the fast refresh implementation you're
using works, you may need to mark the files that create your editor or the
implementation of your LexicalNode subclasses as needing a full refresh.
When things seem broken in dev mode after changing a file, try refreshing the
page first. If that fixes the problem, then mark the file you're working on as
needing a full refresh. For example
Next.js fast refresh
has a // @refresh reset
comment that can be used.