Skip to content

Commit f5c1944

Browse files
committed
Resore an article handle_events_in_ui_frameworks
1 parent 5231825 commit f5c1944

File tree

1 file changed

+74
-66
lines changed

1 file changed

+74
-66
lines changed

apps/website/docs/magazine/handle_events_in_ui_frameworks.md

Lines changed: 74 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -55,75 +55,11 @@ Our application calls it every time when a request for data is failed, and we ne
5555

5656
We need to bound `dataLoadingFailed` and `notification.useNotification` somehow.
5757

58-
Let us take a look on a couple of solutions and find the best one.
59-
60-
### 🔴 Global `notification` service
61-
62-
Ant Design allows using global notification instance.
63-
64-
```ts{7-17}
65-
// model.ts
66-
import { createEvent, createEffect, sample } from 'effector';
67-
import { notification } from 'antd';
68-
69-
const dataLoadingFailed = createEvent<{ reason: string }>();
70-
71-
// Create an Effect to show a notification
72-
const showWarningFx = createEffect((params: { message: string }) => {
73-
notification.warning(params);
74-
});
75-
76-
// Execute it when dataLoadingFailed is happened
77-
sample({
78-
clock: dataLoadingFailed,
79-
fn: ({ reason }) => ({ message: reason }),
80-
target: showWarningFx,
81-
});
82-
```
83-
84-
In this solution it is not possible to use any Ant's settings from React Context, because it does not have access to the React at all. It means that notifications will not be styled properly and could look different from the rest of the application.
85-
86-
So, this is not a solution.
87-
88-
### 🔴 Just `.watch` an [_Event_](https://effector.dev/en/api/effector/event/) in a component
89-
90-
It is possible to call `.watch`-method of an [_Event_](https://effector.dev/en/api/effector/event/) in a component.
91-
92-
```tsx{9-17}
93-
import { useEffect } from 'react';
94-
import { notification } from 'antd';
95-
96-
import { dataLoadingFailed } from './model';
97-
98-
function App() {
99-
const [api, contextHolder] = notification.useNotification();
100-
101-
useEffect(
102-
() =>
103-
dataLoadingFailed.watch(({ reason }) => {
104-
api.warning({
105-
message: reason,
106-
});
107-
}),
108-
[api]
109-
);
110-
111-
return (
112-
<>
113-
{contextHolder}
114-
{/* ...the rest of the application */}
115-
</>
116-
);
117-
}
118-
```
119-
120-
In this solution we do not respect [Fork API rules](/magazine/fork_api_rules), it means that we could have memory leaks, problems with test environments and Storybook-like tools.
121-
122-
So, this is not a solution.
58+
Let us take a look on a ideal solution and a couple of not-so-good solutions.
12359

12460
### 🟢 Save `notification` instance to a [_Store_](https://effector.dev/docs/api/effector/store)
12561

126-
We can combine the previous two solutions and save `notification` API-instance to a [_Store_](https://effector.dev/docs/api/effector/store). Let us create a couple new units to do it.
62+
The best way is saving `notification` API-instance to a [_Store_](https://effector.dev/docs/api/effector/store) and using it thru [_Effect_](https://effector.dev/docs/api/effector/effect). Let us create a couple new units to do it.
12763

12864
```ts
12965
// notifications.ts
@@ -210,6 +146,78 @@ sample({
210146
});
211147
```
212148

149+
Now we have a valid solution to handle [_Events_](https://effector.dev/en/api/effector/event/) on UI-layer without exposing the whole data-flow.
150+
151+
However, if you want to know why other (maybe more obvious) solutions are not so good, you can read about them below 👇
152+
153+
::: details Not-so-good solutions
154+
155+
### 🔴 Global `notification` service
156+
157+
Ant Design allows using global notification instance.
158+
159+
```ts{7-17}
160+
// model.ts
161+
import { createEvent, createEffect, sample } from 'effector';
162+
import { notification } from 'antd';
163+
164+
const dataLoadingFailed = createEvent<{ reason: string }>();
165+
166+
// Create an Effect to show a notification
167+
const showWarningFx = createEffect((params: { message: string }) => {
168+
notification.warning(params);
169+
});
170+
171+
// Execute it when dataLoadingFailed is happened
172+
sample({
173+
clock: dataLoadingFailed,
174+
fn: ({ reason }) => ({ message: reason }),
175+
target: showWarningFx,
176+
});
177+
```
178+
179+
In this solution it is not possible to use any Ant's settings from React Context, because it does not have access to the React at all. It means that notifications will not be styled properly and could look different from the rest of the application.
180+
181+
So, this is not a solution.
182+
183+
### 🔴 Just `.watch` an [_Event_](https://effector.dev/en/api/effector/event/) in a component
184+
185+
It is possible to call `.watch`-method of an [_Event_](https://effector.dev/en/api/effector/event/) in a component.
186+
187+
```tsx{9-17}
188+
import { useEffect } from 'react';
189+
import { notification } from 'antd';
190+
191+
import { dataLoadingFailed } from './model';
192+
193+
function App() {
194+
const [api, contextHolder] = notification.useNotification();
195+
196+
useEffect(
197+
() =>
198+
dataLoadingFailed.watch(({ reason }) => {
199+
api.warning({
200+
message: reason,
201+
});
202+
}),
203+
[api]
204+
);
205+
206+
return (
207+
<>
208+
{contextHolder}
209+
{/* ...the rest of the application */}
210+
</>
211+
);
212+
}
213+
```
214+
215+
In this solution we do not respect [Fork API rules](/magazine/fork_api_rules), it means that we could have memory leaks, problems with test environments and Storybook-like tools.
216+
217+
So, this is not a solution.
218+
219+
:::
220+
213221
## Summary
214222

215223
To bind some UI-framework specific API to Effector's data-flow we need to follow these steps:

0 commit comments

Comments
 (0)