Skip to content

Commit

Permalink
fix(Toaster): pre 18 react fix (#494)
Browse files Browse the repository at this point in the history
  • Loading branch information
amje committed Jan 26, 2023
1 parent 6476cb7 commit 0f0877a
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 103 deletions.
16 changes: 11 additions & 5 deletions src/components/Toaster/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,31 +59,37 @@ 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
import {Toaster} from '@gravity-ui/uikit';
const toaster = new Toaster();
```

or

```js
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 |
Expand Down
25 changes: 21 additions & 4 deletions src/components/Toaster/ToasterSingleton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
Expand All @@ -36,6 +42,7 @@ export class ToasterSingleton {
this.className = className;
this.mobile = mobile;
this.createRootNode();
this.createReactRoot();
this.render();

window[TOASTER_KEY] = this;
Expand Down Expand Up @@ -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 = (
<ToasterProvider
ref={(api) => {
this.componentAPI = api;
}}
>
<ToasterComponent hasPortal={false} mobile={this.mobile} />
</ToasterProvider>,
this.rootNode,
() => Promise.resolve(),
</ToasterProvider>
);

if (this.reactRoot) {
this.reactRoot.render(container);
} else {
ReactDOM.render(container, this.rootNode, () => Promise.resolve());
}
}

private setRootNodeClassName() {
Expand Down
92 changes: 0 additions & 92 deletions src/components/Toaster/ToasterSingletonReact18.tsx

This file was deleted.

1 change: 0 additions & 1 deletion src/components/Toaster/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export {ToasterSingleton as Toaster} from './ToasterSingleton';
export {ToasterSingleton as ToasterReact18} from './ToasterSingletonReact18';
export {Toast} from './Toast/Toast';

export * from './types';
Expand Down
5 changes: 4 additions & 1 deletion src/toaster-singleton-react-18.ts
Original file line number Diff line number Diff line change
@@ -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;

0 comments on commit 0f0877a

Please sign in to comment.