Skip to content

Commit 3dd144a

Browse files
committed
translate useEffectEvent reference
1 parent 951189b commit 3dd144a

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
---
2+
title: useEffectEvent
3+
---
4+
5+
<Intro>
6+
7+
`useEffectEvent` — это хук React, который позволяет вынести не реактивную (не зависящую от состояния или пропсов) логику из эффекта в переиспользуемую функцию, называемую [Effect Event](/learn/separating-events-from-effects#declaring-an-effect-event).
8+
9+
```js
10+
const onSomething = useEffectEvent(callback)
11+
```
12+
13+
</Intro>
14+
15+
<InlineToc />
16+
17+
## Справочник {/*reference*/}
18+
19+
### `useEffectEvent(callback)` {/*useeffectevent*/}
20+
21+
Вызывайте `useEffectEvent` на верхнем уровне вашего компонента, чтобы объявить **Effect Event**.
22+
Effect Event — это функция, которую можно вызывать внутри эффектов (`useEffect`, `useLayoutEffect`, и т.д.):
23+
24+
```js {4-6,11}
25+
import { useEffectEvent, useEffect } from 'react';
26+
27+
function ChatRoom({ roomId, theme }) {
28+
const onConnected = useEffectEvent(() => {
29+
showNotification('Connected!', theme);
30+
});
31+
32+
useEffect(() => {
33+
const connection = createConnection(serverUrl, roomId);
34+
connection.on('connected', () => {
35+
onConnected();
36+
});
37+
connection.connect();
38+
return () => connection.disconnect();
39+
}, [roomId]);
40+
41+
// ...
42+
}
43+
```
44+
45+
[См. другие примеры ниже.](#usage)
46+
47+
#### Параметры {/*parameters*/}
48+
49+
* `callback`: функция, содержащая логику вашего Effect Event.
50+
При определении события через `useEffectEvent`, переданная `callback` всегда получает доступ к **актуальным значениям пропсов и состояния** на момент вызова.
51+
Это помогает избежать проблем с **устаревшими замыканиями** (stale closures).
52+
53+
#### Возвращаемое значение {/*returns*/}
54+
55+
Возвращает функцию Effect Event. Эту функцию можно вызывать внутри `useEffect`, `useLayoutEffect` или `useInsertionEffect`.
56+
57+
#### Замечания {/*caveats*/}
58+
59+
* **Вызывать только внутри эффектов:**
60+
Effect Events должны вызываться *только* внутри эффектов.
61+
Определяйте их непосредственно перед эффектом, который их использует.
62+
Не передавайте их в другие компоненты или хуки.
63+
Линтер [`eslint-plugin-react-hooks`](/reference/eslint-plugin-react-hooks) (версии 6.1.1 и выше) проверяет это ограничение и не даст вызвать Effect Event в неправильном контексте.
64+
65+
* **Не сокращает зависимости:**
66+
Не используйте `useEffectEvent` как способ “избежать” добавления зависимостей в массив зависимостей эффекта.
67+
Это может скрыть ошибки и ухудшить читаемость кода.
68+
Лучше явно указывать зависимости или использовать `ref`, если нужно сравнивать предыдущие значения.
69+
70+
* **Используется для не реактивной логики:**
71+
Применяйте `useEffectEvent` только для логики, не зависящей напрямую от изменений состояния или пропсов.
72+
___
73+
74+
## Применение {/*usage*/}
75+
76+
### Чтение актуальных пропсов и состояния {/*reading-the-latest-props-and-state*/}
77+
78+
Обычно, когда вы используете реактивные значения (пропсы или состояние) внутри эффекта,
79+
нужно добавить их в массив зависимостей.
80+
Это гарантирует, что эффект выполнится снова при изменении этих значений — что чаще всего и нужно.
81+
82+
Но бывают случаи, когда необходимо **читать самые свежие значения пропсов или состояния**,
83+
не вызывая при этом повторного выполнения эффекта при каждом их изменении.
84+
85+
Чтобы [читать актуальные значения пропсов или состояния](/learn/separating-events-from-effects#reading-latest-props-and-state-with-effect-events)
86+
внутри эффекта без превращения их в реактивные зависимости, включите их в Effect Event.
87+
88+
```js {7-9,12}
89+
import { useEffect, useContext, useEffectEvent } from 'react';
90+
91+
function Page({ url }) {
92+
const { items } = useContext(ShoppingCartContext);
93+
const numberOfItems = items.length;
94+
95+
const onNavigate = useEffectEvent((visitedUrl) => {
96+
logVisit(visitedUrl, numberOfItems);
97+
});
98+
99+
useEffect(() => {
100+
onNavigate(url);
101+
}, [url]);
102+
103+
// ...
104+
}
105+
```
106+
107+
В этом примере эффект должен выполняться повторно при изменении `url` (чтобы зафиксировать посещение новой страницы), но **не должен** выполняться заново при изменении `numberOfItems`. Оборачивая логику логирования в Effect Event, мы делаем `numberOfItems` *нереактивным*: оно всегда читается в своём актуальном виде, но не вызывает повторный рендер или перезапуск эффекта. При этом вы можете передавать реактивные значения, такие как `url`, в аргументах Effect Event — чтобы сохранить их реактивность и при этом иметь доступ к свежим нереактивным данным внутри события.

0 commit comments

Comments
 (0)