packages/lexical-website/docs/react/faq.md
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):
useMemo calls are cached across StrictMode re-renders, so
only one editor will be used for both renders. If you have a useEffect
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 the LexicalComposerContext
which includes the editor and theme)editorState argument in the config when creating the
editor, it will only be called once when the editor is created.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.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:
useLexicalComposerContext() in a component that is
not a child of the LexicalComposer. If you need to do that, you need to
pass the context or editor up the tree with something like EditorRefPlugin.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 in package.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.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.