From 440ed7ebc8dee1f1159cf608018c34cb69f4a8f7 Mon Sep 17 00:00:00 2001 From: Andrey Morozov Date: Thu, 12 Jan 2023 23:00:13 +0300 Subject: [PATCH] fix(Toaster): swap namings in singletons --- src/components/Toaster/README.md | 13 +++++++++++++ src/components/Toaster/ToasterSingleton.tsx | 16 ++++++---------- ...gletonOld.tsx => ToasterSingletonReact18.tsx} | 16 ++++++++++------ src/components/Toaster/index.ts | 2 +- src/toaster-singleton-react-18.ts | 4 ++++ 5 files changed, 34 insertions(+), 17 deletions(-) rename src/components/Toaster/{ToasterSingletonOld.tsx => ToasterSingletonReact18.tsx} (87%) create mode 100644 src/toaster-singleton-react-18.ts diff --git a/src/components/Toaster/README.md b/src/components/Toaster/README.md index 93e866cb0..1bf0d1de6 100644 --- a/src/components/Toaster/README.md +++ b/src/components/Toaster/README.md @@ -59,6 +59,8 @@ const FoobarWithToaster = withToaster()(FoobarComponent); ## Usage as singleton +### React < 18 + ```js import {Toaster} from '@gravity-ui/uikit'; const toaster = new Toaster(); @@ -68,6 +70,17 @@ const toaster = new Toaster(); import {toaster} from '@gravity-ui/uikit/toaster-singleton'; ``` +### React 18 + +```js +import {ToasterReact18} from '@gravity-ui/uikit'; +const toaster = new ToasterReact18(); +``` + +```js +import {toaster} from '@gravity-ui/uikit/toaster-singleton-react-18'; +``` + Toaster has singleton, so when initialized in different parts of the application, the same instance will be returned. On initialization it is possible to pass className, that will be assigned to dom-element which is wrapping all toasts. diff --git a/src/components/Toaster/ToasterSingleton.tsx b/src/components/Toaster/ToasterSingleton.tsx index ee7f9c9aa..0fffd6541 100644 --- a/src/components/Toaster/ToasterSingleton.tsx +++ b/src/components/Toaster/ToasterSingleton.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import ReactDOMClient from 'react-dom/client'; +import ReactDOM from 'react-dom'; import get from 'lodash/get'; import {block} from '../utils/cn'; import type {ToasterArgs, ToasterPublicMethods, ToastProps} from './types'; @@ -17,7 +17,6 @@ declare global { export class ToasterSingleton { private rootNode!: HTMLDivElement; - private reactRoot!: ReactDOMClient.Root; private className = ''; private mobile = false; private componentAPI: null | ToasterPublicMethods = null; @@ -38,15 +37,14 @@ export class ToasterSingleton { this.className = additionalClass; this.mobile = mobile; this.createRootNode(); - this.createReactRoot(); this.render(); window[TOASTER_KEY] = this; } destroy() { - this.reactRoot.unmount(); - this.rootNode.remove(); + ReactDOM.unmountComponentAtNode(this.rootNode); + document.body.removeChild(this.rootNode); } add = (options: ToastProps) => { @@ -71,12 +69,8 @@ export class ToasterSingleton { document.body.appendChild(this.rootNode); } - private createReactRoot() { - this.reactRoot = ReactDOMClient.createRoot(this.rootNode); - } - private render() { - this.reactRoot.render( + ReactDOM.render( { this.componentAPI = api; @@ -84,6 +78,8 @@ export class ToasterSingleton { > , + this.rootNode, + () => Promise.resolve(), ); } diff --git a/src/components/Toaster/ToasterSingletonOld.tsx b/src/components/Toaster/ToasterSingletonReact18.tsx similarity index 87% rename from src/components/Toaster/ToasterSingletonOld.tsx rename to src/components/Toaster/ToasterSingletonReact18.tsx index 0fffd6541..ee7f9c9aa 100644 --- a/src/components/Toaster/ToasterSingletonOld.tsx +++ b/src/components/Toaster/ToasterSingletonReact18.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import ReactDOM from 'react-dom'; +import ReactDOMClient from 'react-dom/client'; import get from 'lodash/get'; import {block} from '../utils/cn'; import type {ToasterArgs, ToasterPublicMethods, ToastProps} from './types'; @@ -17,6 +17,7 @@ declare global { export class ToasterSingleton { private rootNode!: HTMLDivElement; + private reactRoot!: ReactDOMClient.Root; private className = ''; private mobile = false; private componentAPI: null | ToasterPublicMethods = null; @@ -37,14 +38,15 @@ export class ToasterSingleton { this.className = additionalClass; this.mobile = mobile; this.createRootNode(); + this.createReactRoot(); this.render(); window[TOASTER_KEY] = this; } destroy() { - ReactDOM.unmountComponentAtNode(this.rootNode); - document.body.removeChild(this.rootNode); + this.reactRoot.unmount(); + this.rootNode.remove(); } add = (options: ToastProps) => { @@ -69,8 +71,12 @@ export class ToasterSingleton { document.body.appendChild(this.rootNode); } + private createReactRoot() { + this.reactRoot = ReactDOMClient.createRoot(this.rootNode); + } + private render() { - ReactDOM.render( + this.reactRoot.render( { this.componentAPI = api; @@ -78,8 +84,6 @@ export class ToasterSingleton { > , - this.rootNode, - () => Promise.resolve(), ); } diff --git a/src/components/Toaster/index.ts b/src/components/Toaster/index.ts index abc6deeca..e82778d33 100644 --- a/src/components/Toaster/index.ts +++ b/src/components/Toaster/index.ts @@ -1,5 +1,5 @@ export {ToasterSingleton as Toaster} from './ToasterSingleton'; -export {ToasterSingleton as ToasterOld} from './ToasterSingletonOld'; +export {ToasterSingleton as ToasterReact18} from './ToasterSingletonReact18'; export {Toast} from './Toast/Toast'; export * from './types'; diff --git a/src/toaster-singleton-react-18.ts b/src/toaster-singleton-react-18.ts new file mode 100644 index 000000000..1b6a70b2c --- /dev/null +++ b/src/toaster-singleton-react-18.ts @@ -0,0 +1,4 @@ +import {ToasterSingleton} from './components/Toaster/ToasterSingletonReact18'; + +// in SSR case +export const toaster = typeof window === 'object' ? new ToasterSingleton() : null;