diff --git a/src/components/Toaster/README.md b/src/components/Toaster/README.md
index 1bf0d1de6f..a68edb7a28 100644
--- a/src/components/Toaster/README.md
+++ b/src/components/Toaster/README.md
@@ -59,6 +59,9 @@ const FoobarWithToaster = withToaster()(FoobarComponent);
## Usage as singleton
+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.
+
### React < 18
```js
@@ -66,6 +69,8 @@ import {Toaster} from '@gravity-ui/uikit';
const toaster = new Toaster();
```
+or
+
```js
import {toaster} from '@gravity-ui/uikit/toaster-singleton';
```
@@ -73,17 +78,18 @@ import {toaster} from '@gravity-ui/uikit/toaster-singleton';
### React 18
```js
-import {ToasterReact18} from '@gravity-ui/uikit';
-const toaster = new ToasterReact18();
+import ReactDOMClient from 'react-dom/client';
+import {Toaster} from '@gravity-ui/uikit';
+Toaster.injectReactDOMClient(ReactDOMClient);
+const toaster = new Toaster();
```
+or
+
```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.
-
## Constructor arguments
| Parameter | Type | Default | Description |
diff --git a/src/components/Toaster/ToasterSingleton.tsx b/src/components/Toaster/ToasterSingleton.tsx
index 634b7b5268..0ae7e08d3d 100644
--- a/src/components/Toaster/ToasterSingleton.tsx
+++ b/src/components/Toaster/ToasterSingleton.tsx
@@ -8,6 +8,7 @@ import {ToasterComponent} from './ToasterComponent/ToasterComponent';
const TOASTER_KEY: unique symbol = Symbol('Toaster instance key');
const bToaster = block('toaster');
+let ReactDOMClient: any;
declare global {
interface Window {
@@ -16,7 +17,12 @@ declare global {
}
export class ToasterSingleton {
+ static injectReactDOMClient(client: any) {
+ ReactDOMClient = client;
+ }
+
private rootNode!: HTMLDivElement;
+ private reactRoot!: any;
private className = '';
private mobile = false;
private componentAPI: null | ToasterPublicMethods = null;
@@ -36,6 +42,7 @@ export class ToasterSingleton {
this.className = className;
this.mobile = mobile;
this.createRootNode();
+ this.createReactRoot();
this.render();
window[TOASTER_KEY] = this;
@@ -68,18 +75,28 @@ export class ToasterSingleton {
document.body.appendChild(this.rootNode);
}
+ private createReactRoot() {
+ if (ReactDOMClient) {
+ this.reactRoot = ReactDOMClient.createRoot(this.rootNode);
+ }
+ }
+
private render() {
- ReactDOM.render(
+ const container = (
{
this.componentAPI = api;
}}
>
- ,
- this.rootNode,
- () => Promise.resolve(),
+
);
+
+ if (this.reactRoot) {
+ this.reactRoot.render(container);
+ } else {
+ ReactDOM.render(container, this.rootNode, () => Promise.resolve());
+ }
}
private setRootNodeClassName() {
diff --git a/src/components/Toaster/ToasterSingletonReact18.tsx b/src/components/Toaster/ToasterSingletonReact18.tsx
deleted file mode 100644
index fd3a63dcf3..0000000000
--- a/src/components/Toaster/ToasterSingletonReact18.tsx
+++ /dev/null
@@ -1,92 +0,0 @@
-import React from 'react';
-import ReactDOMClient from 'react-dom/client';
-import get from 'lodash/get';
-import {block} from '../utils/cn';
-import type {ToasterArgs, ToasterPublicMethods, ToastProps} from './types';
-import {ToasterProvider} from './Provider/ToasterProvider';
-import {ToasterComponent} from './ToasterComponent/ToasterComponent';
-
-const TOASTER_KEY: unique symbol = Symbol('Toaster instance key');
-const bToaster = block('toaster');
-
-declare global {
- interface Window {
- [TOASTER_KEY]: ToasterSingleton;
- }
-}
-
-export class ToasterSingleton {
- private rootNode!: HTMLDivElement;
- private reactRoot!: ReactDOMClient.Root;
- private className = '';
- private mobile = false;
- private componentAPI: null | ToasterPublicMethods = null;
-
- constructor(args?: ToasterArgs) {
- const className = get(args, ['className'], '');
- const mobile = get(args, ['mobile'], false);
-
- if (window[TOASTER_KEY] instanceof ToasterSingleton) {
- const me = window[TOASTER_KEY];
- me.className = className;
- me.mobile = mobile;
- me.setRootNodeClassName();
- return me;
- }
-
- this.className = className;
- this.mobile = mobile;
- this.createRootNode();
- this.createReactRoot();
- this.render();
-
- window[TOASTER_KEY] = this;
- }
-
- destroy() {
- this.reactRoot.unmount();
- this.rootNode.remove();
- }
-
- add = (options: ToastProps) => {
- this.componentAPI?.add(options);
- };
-
- remove = (name: string) => {
- this.componentAPI?.remove(name);
- };
-
- removeAll = () => {
- this.componentAPI?.removeAll();
- };
-
- update = (name: string, overrideOptions: Partial) => {
- this.componentAPI?.update(name, overrideOptions);
- };
-
- private createRootNode() {
- this.rootNode = document.createElement('div');
- this.setRootNodeClassName();
- document.body.appendChild(this.rootNode);
- }
-
- private createReactRoot() {
- this.reactRoot = ReactDOMClient.createRoot(this.rootNode);
- }
-
- private render() {
- this.reactRoot.render(
- {
- this.componentAPI = api;
- }}
- >
-
- ,
- );
- }
-
- private setRootNodeClassName() {
- this.rootNode.className = bToaster({mobile: this.mobile}, this.className);
- }
-}
diff --git a/src/components/Toaster/index.ts b/src/components/Toaster/index.ts
index e82778d332..58dffca04d 100644
--- a/src/components/Toaster/index.ts
+++ b/src/components/Toaster/index.ts
@@ -1,5 +1,4 @@
export {ToasterSingleton as Toaster} from './ToasterSingleton';
-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
index 1b6a70b2cb..3b2e8497a6 100644
--- a/src/toaster-singleton-react-18.ts
+++ b/src/toaster-singleton-react-18.ts
@@ -1,4 +1,7 @@
-import {ToasterSingleton} from './components/Toaster/ToasterSingletonReact18';
+import ReactDOMClient from 'react-dom/client';
+import {ToasterSingleton} from './components/Toaster/ToasterSingleton';
+
+ToasterSingleton.injectReactDOMClient(ReactDOMClient);
// in SSR case
export const toaster = typeof window === 'object' ? new ToasterSingleton() : null;