From 88bac4de05e13330e47c8f582339c85fe292540a Mon Sep 17 00:00:00 2001 From: Mikhail Vialov Date: Fri, 5 Jul 2024 15:48:35 +0200 Subject: [PATCH] #4979 - Support for Strict mode --- example/src/App.tsx | 6 +-- packages/ketcher-react/src/Editor.tsx | 53 +++++++++++++++------------ 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/example/src/App.tsx b/example/src/App.tsx index 317bb56da6..85321934d0 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -1,6 +1,6 @@ import 'ketcher-react/dist/index.css'; -import { useState } from 'react'; +import { useState, StrictMode } from 'react'; import { ButtonsConfig, Editor, InfoModal } from 'ketcher-react'; import { Ketcher, @@ -71,7 +71,7 @@ const App = () => { ) : ( - <> + { setHasError(true); @@ -105,7 +105,7 @@ const App = () => { }} /> )} - + ); }; diff --git a/packages/ketcher-react/src/Editor.tsx b/packages/ketcher-react/src/Editor.tsx index fc86f33e99..7b47a0efaf 100644 --- a/packages/ketcher-react/src/Editor.tsx +++ b/packages/ketcher-react/src/Editor.tsx @@ -32,7 +32,7 @@ import { ketcherInitEventName, KETCHER_ROOT_NODE_CLASS_NAME, } from './constants'; -import { createRoot } from 'react-dom/client'; +import { createRoot, Root } from 'react-dom/client'; const mediaSizes = { smallWidth: 1040, @@ -43,38 +43,43 @@ interface EditorProps extends Omit { onInit?: (ketcher: Ketcher) => void; } +// This is the biggest crutch in the wild west function Editor(props: EditorProps) { + const initPromiseRef = useRef | null>(null); + const appRootRef = useRef(null); + const rootElRef = useRef(null); - const { onInit } = props; + const { height, width } = useResizeObserver({ ref: rootElRef, }); - useEffect(() => { - const appRoot = createRoot(rootElRef.current as HTMLDivElement); - init({ + const initKetcher = () => { + appRootRef.current = createRoot(rootElRef.current as HTMLDivElement); + + initPromiseRef.current = init({ ...props, element: rootElRef.current, - appRoot, - }).then( - ({ - ketcher, - ketcherId, - }: { - ketcher: Ketcher | undefined; - ketcherId: string; - }) => { - if (typeof onInit === 'function' && ketcher) { - onInit(ketcher); - const ketcherInitEvent = new Event(ketcherInitEventName(ketcherId)); - window.dispatchEvent(ketcherInitEvent); - } - }, - ); + appRoot: appRootRef.current, + }); + initPromiseRef.current?.then(({ ketcher, ketcherId }) => { + if (typeof props.onInit === 'function' && ketcher) { + props.onInit(ketcher); + const ketcherInitEvent = new Event(ketcherInitEventName(ketcherId)); + window.dispatchEvent(ketcherInitEvent); + } + }); + }; + useEffect(() => { + if (initPromiseRef.current === null) { + initKetcher(); + } else { + initPromiseRef.current?.finally(() => initKetcher()); + } + return () => { - // setTimeout is used to disable the warn msg from react "Attempted to synchronously unmount a root while React was already rendering" - setTimeout(() => { - appRoot.unmount(); + initPromiseRef.current?.then(() => { + appRootRef.current?.unmount(); }); }; // TODO: provide the list of dependencies after implementing unsubscribe function