From 3dd144ab3ac2817d394b07f7a350496566f2986b Mon Sep 17 00:00:00 2001 From: Sergey Bocharov Date: Sat, 11 Oct 2025 21:05:48 +0100 Subject: [PATCH 1/3] translate useEffectEvent reference --- src/content/reference/react/useEffectEvent.md | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 src/content/reference/react/useEffectEvent.md diff --git a/src/content/reference/react/useEffectEvent.md b/src/content/reference/react/useEffectEvent.md new file mode 100644 index 000000000..2cb7575aa --- /dev/null +++ b/src/content/reference/react/useEffectEvent.md @@ -0,0 +1,107 @@ +--- +title: useEffectEvent +--- + + + +`useEffectEvent` — это хук React, который позволяет вынести не реактивную (не зависящую от состояния или пропсов) логику из эффекта в переиспользуемую функцию, называемую [Effect Event](/learn/separating-events-from-effects#declaring-an-effect-event). + +```js +const onSomething = useEffectEvent(callback) +``` + + + + + +## Справочник {/*reference*/} + +### `useEffectEvent(callback)` {/*useeffectevent*/} + +Вызывайте `useEffectEvent` на верхнем уровне вашего компонента, чтобы объявить **Effect Event**. +Effect Event — это функция, которую можно вызывать внутри эффектов (`useEffect`, `useLayoutEffect`, и т.д.): + +```js {4-6,11} +import { useEffectEvent, useEffect } from 'react'; + +function ChatRoom({ roomId, theme }) { + const onConnected = useEffectEvent(() => { + showNotification('Connected!', theme); + }); + + useEffect(() => { + const connection = createConnection(serverUrl, roomId); + connection.on('connected', () => { + onConnected(); + }); + connection.connect(); + return () => connection.disconnect(); + }, [roomId]); + + // ... +} +``` + +[См. другие примеры ниже.](#usage) + +#### Параметры {/*parameters*/} + +* `callback`: функция, содержащая логику вашего Effect Event. + При определении события через `useEffectEvent`, переданная `callback` всегда получает доступ к **актуальным значениям пропсов и состояния** на момент вызова. + Это помогает избежать проблем с **устаревшими замыканиями** (stale closures). + +#### Возвращаемое значение {/*returns*/} + +Возвращает функцию Effect Event. Эту функцию можно вызывать внутри `useEffect`, `useLayoutEffect` или `useInsertionEffect`. + +#### Замечания {/*caveats*/} + +* **Вызывать только внутри эффектов:** + Effect Events должны вызываться *только* внутри эффектов. + Определяйте их непосредственно перед эффектом, который их использует. + Не передавайте их в другие компоненты или хуки. + Линтер [`eslint-plugin-react-hooks`](/reference/eslint-plugin-react-hooks) (версии 6.1.1 и выше) проверяет это ограничение и не даст вызвать Effect Event в неправильном контексте. + +* **Не сокращает зависимости:** + Не используйте `useEffectEvent` как способ “избежать” добавления зависимостей в массив зависимостей эффекта. + Это может скрыть ошибки и ухудшить читаемость кода. + Лучше явно указывать зависимости или использовать `ref`, если нужно сравнивать предыдущие значения. + +* **Используется для не реактивной логики:** + Применяйте `useEffectEvent` только для логики, не зависящей напрямую от изменений состояния или пропсов. +___ + +## Применение {/*usage*/} + +### Чтение актуальных пропсов и состояния {/*reading-the-latest-props-and-state*/} + +Обычно, когда вы используете реактивные значения (пропсы или состояние) внутри эффекта, +нужно добавить их в массив зависимостей. +Это гарантирует, что эффект выполнится снова при изменении этих значений — что чаще всего и нужно. + +Но бывают случаи, когда необходимо **читать самые свежие значения пропсов или состояния**, +не вызывая при этом повторного выполнения эффекта при каждом их изменении. + +Чтобы [читать актуальные значения пропсов или состояния](/learn/separating-events-from-effects#reading-latest-props-and-state-with-effect-events) +внутри эффекта без превращения их в реактивные зависимости, включите их в Effect Event. + +```js {7-9,12} +import { useEffect, useContext, useEffectEvent } from 'react'; + +function Page({ url }) { + const { items } = useContext(ShoppingCartContext); + const numberOfItems = items.length; + + const onNavigate = useEffectEvent((visitedUrl) => { + logVisit(visitedUrl, numberOfItems); + }); + + useEffect(() => { + onNavigate(url); + }, [url]); + + // ... +} +``` + +В этом примере эффект должен выполняться повторно при изменении `url` (чтобы зафиксировать посещение новой страницы), но **не должен** выполняться заново при изменении `numberOfItems`. Оборачивая логику логирования в Effect Event, мы делаем `numberOfItems` *нереактивным*: оно всегда читается в своём актуальном виде, но не вызывает повторный рендер или перезапуск эффекта. При этом вы можете передавать реактивные значения, такие как `url`, в аргументах Effect Event — чтобы сохранить их реактивность и при этом иметь доступ к свежим нереактивным данным внутри события. \ No newline at end of file From 8883fc6a6479e676e0c4ca0aeddad0ed044781f2 Mon Sep 17 00:00:00 2001 From: Sergey Bocharov Date: Sat, 11 Oct 2025 21:16:29 +0100 Subject: [PATCH 2/3] translate useEffectEvent reference --- src/content/reference/react/useEffectEvent.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/content/reference/react/useEffectEvent.md b/src/content/reference/react/useEffectEvent.md index 2cb7575aa..a49f06d43 100644 --- a/src/content/reference/react/useEffectEvent.md +++ b/src/content/reference/react/useEffectEvent.md @@ -4,7 +4,7 @@ title: useEffectEvent -`useEffectEvent` — это хук React, который позволяет вынести не реактивную (не зависящую от состояния или пропсов) логику из эффекта в переиспользуемую функцию, называемую [Effect Event](/learn/separating-events-from-effects#declaring-an-effect-event). +Хук `useEffectEvent` позволяет вынести не реактивную (не зависящую от состояния или пропсов) логику из эффекта в переиспользуемую функцию, называемую [Effect Event](/learn/separating-events-from-effects#declaring-an-effect-event). ```js const onSomething = useEffectEvent(callback) @@ -18,8 +18,7 @@ const onSomething = useEffectEvent(callback) ### `useEffectEvent(callback)` {/*useeffectevent*/} -Вызывайте `useEffectEvent` на верхнем уровне вашего компонента, чтобы объявить **Effect Event**. -Effect Event — это функция, которую можно вызывать внутри эффектов (`useEffect`, `useLayoutEffect`, и т.д.): +Чтобы объявить **Effect Event** функцию, вызовите `useEffectEvent` на верхнем уровне вашего компонента. Effect Event функцию можно безопасно вызывать внутри эффектов (`useEffect`, `useLayoutEffect`, и т.д.): ```js {4-6,11} import { useEffectEvent, useEffect } from 'react'; From 8db7071f4907302d042115ffc11da2c6f60f8b02 Mon Sep 17 00:00:00 2001 From: Sergey Bocharov Date: Sat, 11 Oct 2025 21:26:35 +0100 Subject: [PATCH 3/3] translate useEffectEvent reference --- src/content/reference/react/useEffectEvent.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/content/reference/react/useEffectEvent.md b/src/content/reference/react/useEffectEvent.md index a49f06d43..d69104d4a 100644 --- a/src/content/reference/react/useEffectEvent.md +++ b/src/content/reference/react/useEffectEvent.md @@ -51,7 +51,7 @@ function ChatRoom({ roomId, theme }) { #### Возвращаемое значение {/*returns*/} -Возвращает функцию Effect Event. Эту функцию можно вызывать внутри `useEffect`, `useLayoutEffect` или `useInsertionEffect`. +Возвращает функцию Effect Event, которую можно вызывать внутри `useEffect`, `useLayoutEffect` или `useInsertionEffect`. #### Замечания {/*caveats*/} @@ -68,13 +68,14 @@ function ChatRoom({ roomId, theme }) { * **Используется для не реактивной логики:** Применяйте `useEffectEvent` только для логики, не зависящей напрямую от изменений состояния или пропсов. + ___ ## Применение {/*usage*/} ### Чтение актуальных пропсов и состояния {/*reading-the-latest-props-and-state*/} -Обычно, когда вы используете реактивные значения (пропсы или состояние) внутри эффекта, +Когда вы используете реактивные значения (пропсы или состояние) внутри эффекта, нужно добавить их в массив зависимостей. Это гарантирует, что эффект выполнится снова при изменении этих значений — что чаще всего и нужно.