I have an app that imports a private NPM package that contains a text editor component that is powered by LexicalComposer. Currently in my app, I am trying to upgrade to version 18 of React and I am running into the following error 'TypeError: destroy is not a function' when my implemented Lexical editor component attempts to unmount. I have mainly been using the console to determine that the error may be coming from Lexical's implementation of LexcialComposer
With React 18, I know that this error usually implies there is an incorrect usage of asynchronous actions within useEffect() react hooks. I am wondering if Lexical support React 18? and if it does, where would that error be coming from? and how to fix it.
The following is the implementation of the Lexical text editor that leverages LexicalComposer.
import React from 'react';
import { LexicalComposer } from '@lexical/react/LexicalComposer';
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
import { ContentEditable } from '@lexical/react/LexicalContentEditable';
import LexicalErrorBoundary from '@lexical/react/LexicalErrorBoundary';
import { StandardPlugins } from '@myapp/myapp-lexical-react';
import styles from './myappLexicalEditor.module.scss';
import classNames from 'classnames/bind';
import { myappLexicalEditorTheme } from './myappLexicalEditorTheme';
import { MyappLexicalEditorProps } from './myappLexicalEditor.types';
const cx = classNames.bind(styles);
/**
* My App implementation of the Lexical Rich Text Editor
*/
const LexicalEditor = ({
editorConfig,
children,
toolbars,
readOnly,
onEditorChange,
editorClass,
editorStyle,
editorContainerClass,
editorContainerStyle,
editorChildren,
toolbarClass,
placeholder,
plugins,
disableHistoryPlugin,
}: MyappLexicalEditorProps) => {
const Placeholder = placeholder || null;
return (
<LexicalComposer initialConfig={{ ...editorConfig, theme: { ...myappLexicalEditorTheme, ...editorConfig.theme }, editable: !readOnly }}>
<div className={toolbarClass}>
<>
{Array.isArray(toolbars) &&
toolbars.map((toolbar, i) => {
const { ToolbarComponent, props, showToolbar } = toolbar;
const finalShowToolbar = showToolbar !== undefined ? showToolbar : !readOnly;
return finalShowToolbar ? <ToolbarComponent key={i} {...props} /> : '';
})
}
</>
</div>
<div>
<div>
<divstyle={editorStyle} >
<RichTextPlugin
contentEditable={<ContentEditable />}
ErrorBoundary={LexicalErrorBoundary}
placeholder={!readOnly ? Placeholder : null}
/>
{editorChildren}
</div>
</div>
</div>
<StandardPlugins onChange={onEditorChange} disableHistory={Boolean(disableHistoryPlugin)}/>
<>
{plugins && plugins.map((pluginObj, i) => {
const { PluginComponent, props } = pluginObj;
return <PluginComponent key={i} {...props} />;
})}
</>
{children}
</LexicalComposer>
);
};
export default LexicalEditor;
Below is the error I am seeing and where I think the error is being traced back from.
Uncaught TypeError: destroy is not a function
at safelyCallDestroy (react-dom.development.js:22928:5)
at commitHookEffectListUnmount (react-dom.development.js:23096:11)
at commitPassiveUnmountInsideDeletedTreeOnFiber (react-dom.development.js:25094:11)
at commitPassiveUnmountEffectsInsideOfDeletedTree_begin (react-dom.development.js:25044:5)
at commitPassiveUnmountEffects_begin (react-dom.development.js:24952:11)
at commitPassiveUnmountEffects (react-dom.development.js:24937:3)
at flushPassiveEffectsImpl (react-dom.development.js:27034:3)
at flushPassiveEffects (react-dom.development.js:26980:14)
at commitRootImpl (react-dom.development.js:26931:5)
at commitRoot (react-dom.development.js:26678:5)
The above error occurred in the <observerComponent> component:
at observerComponent (webpack-internal:///./node_modules/mobx-react-lite/es/observer.js:51:73)
at div
at observerComponent (webpack-internal:///./node_modules/mobx-react-lite/es/observer.js:51:73)
at _class (webpack-internal:///./frontend/js/stores/index.js:163:88)
at I18nextWithTranslation (webpack-internal:///./node_modules/react-i18next/dist/es/withTranslation.js:28:31)
at div
at LexicalComposer (webpack-internal:///./node_modules/@lexical/react/LexicalComposer.dev.js:43:3)
at w (webpack-internal:///./node_modules/@myapp/myapp-lexical-react/lib/components/MyappLexicalEditor/MyappLexicalEditor.es.js:29:172)
at div
at div
at Summary (webpack-internal:///./frontend/js/components/reusableComponents/Deal/ResponseDetails/components/SummarySection/Summary/summary.js:41:25)
at div
at SummarySection (webpack-internal:///./frontend/js/components/reusableComponents/Deal/ResponseDetails/components/SummarySection/summarySection.js:23:32)
at div
at observerComponent (webpack-internal:///./node_modules/mobx-react-lite/es/observer.js:51:73)
at _class (webpack-internal:///./frontend/js/stores/index.js:163:88)
at I18nextWithTranslation (webpack-internal:///./node_modules/react-i18next/dist/es/withTranslation.js:28:31)
at div
at TabPane (webpack-internal:///./node_modules/rc-tabs/es/TabPanelList/TabPane.js:16:24)
at div
at div
at TabPanelList (webpack-internal:///./node_modules/rc-tabs/es/TabPanelList/index.js:16:17)
at div
at Tabs (webpack-internal:///./node_modules/rc-tabs/es/Tabs.js:73:17)
at Tabs (webpack-internal:///./node_modules/antd/es/tabs/index.js:45:17)
at div
at observerComponent (webpack-internal:///./node_modules/mobx-react-lite/es/observer.js:51:73)
at I18nextWithTranslation (webpack-internal:///./node_modules/react-i18next/dist/es/withTranslation.js:28:31)
at _class (webpack-internal:///./frontend/js/stores/index.js:163:88)
at I18nextWithTranslation (webpack-internal:///./node_modules/react-i18next/dist/es/withTranslation.js:28:31)
at Route (webpack-internal:///./node_modules/react-router/esm/react-router.js:648:29)
at Switch (webpack-internal:///./node_modules/react-router/esm/react-router.js:850:29)
at div
at Container (webpack-internal:///./node_modules/@myapp/myapp-ui/components/container/Container.js:18:22)
at observerComponent (webpack-internal:///./node_modules/mobx-react-lite/es/observer.js:51:73)
at _class (webpack-internal:///./frontend/js/stores/index.js:163:88)
at I18nextWithTranslation (webpack-internal:///./node_modules/react-i18next/dist/es/withTranslation.js:28:31)
I have tried wrapping the Component in an error boundary in an attempt to at least see more information about the error. I had no luck there.
I also tried attaching a useRef ref to the main implementation in my bigger app and using a useEffect() callback to assign it to null when it unmounts.