Каковы последствия использования дополнительных зависимостей в useEffect?

Скажем, у меня есть этот код:

useEffect(() => {
  makeBreakfast(pig)
}, [pig, chicken])

makeBreakfast вызывается pig, и логично, что он находится в зависимостях. Однако в этом фиктивном примере мы также хотим приготовить завтрак с pig всякий раз, когда chicken изменяется (я не знаю почему, это просто пример!). По сути, мы слушаем изменения в chicken, хотя он и не участвует в функции makeBreakfast.

useEffect(() => {
  if (breakfastMadeRef.current) {
    farmerFed.current = true;
  }
}, [farmerIndex])

В этом примере реальной зависимости нет, но мы хотим проверить/изменить ссылки на изменения в farmerIndex (опять же, просто фиктивный пример).

Есть ли какие-либо последствия для этой «дополнительной» зависимости? Мне это кажется нечистым, поскольку я ожидал (из документов и других мест, которые я видел/использовал useEffect), что все зависимости будут использоваться в теле функции эффекта.

Если я использую правило react-hooks/exhaustive-deps, как и ожидалось, претензий нет. Поэтому я склонен думать, что это нормально, хотя это может ввести в заблуждение/сбить с толку, если мы в конечном итоге добавим всю ферму в список зависимостей?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
5
0
369
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Последствий нет, но обычно это свидетельствует о запахе кода.

Массив, предоставленный useEffect(), лучше рассматривать как «этот эффект синхронизируется с этими данными», а не как «запускать этот эффект каждый раз, когда эти данные изменяются». Если эффект на самом деле не использует предоставленные ему данные, то его не нужно повторно запускать при изменении.

Обычно посторонние переменные, предоставляемые useEffect(), в конечном итоге либо становятся производным состоянием, либо изменение переменной инициируется функцией, которая сама должна быть источником мутации.

Трудно сказать много без более конкретного примера; примеры, которые вы выбрали, вряд ли появятся в реальном мире.

Я предполагаю, что следствием этого является усиление запаха кода. Кроме того, я определенно видел код, похожий на оба в кодовых базах, над которыми мне приходилось работать (я сделал минимальную настройку примера фермера)... В основном это связано с компонентами, которые обертывают другие и используют дочернее состояние (например, индекс страницы на «наблюдателе» изменения размера), но у меня нет конкретного примера, которым я мог бы поделиться.

AncientSwordRage 22.12.2020 13:23

Вот пример: у меня есть причудливая визуализация диаграммы SVG, которая меняет свой внешний вид в зависимости от нескольких разных реквизитов. Я хочу автоматически подгонять viewBox к содержимому отображаемого SVG, но только при изменении определенных реквизитов; пропсы, сильно влияющие на геометрию графика (если я буду делать это при каждой смене пропсов, будет слишком дергано). Функция автоподбора на самом деле не принимает никаких реквизитов, которые делает диаграмма, ей просто нужна ссылка на отображаемый элемент SVG. Итак, я использую useEffect, который вызывает функцию автоподбора, и массив из нескольких «дополнительных» зависимостей.

V. Rubinetti 15.06.2022 22:37

Вы должны использовать useLayoutEffect для этого, а не useEffect. То, что я сказал, конкретно относится к useEffect; useLayoutEffect предназначен для использования для манипулирования DOM, как вы упомянули, и в этих случаях это имеет смысл

Dan 17.06.2022 17:53

Принятый ответ неверен. Дополнительные зависимости в массиве useEffect заставят ваш эффект сработать, когда они изменятся, независимо от того, используются они или нет внутри обратного вызова. Вы можете попробовать следующий компонент, и вы увидите, что console.info() будет печатать каждый раз при нажатии кнопки, даже если в нем не используется зависимость:

import { useEffect, useState } from "react";

export default function App() {
  const [toggle, setToggle] = useState(false);

  useEffect(() => {
    console.info("Toggled"); // Will print everytime when toggle changes
  }, [toggle]);

  return <button onClick = {() => setToggle(!toggle)}>Thing</button>;
}

Пожалуйста, добавьте дополнительную информацию, чтобы расширить свой ответ, например, рабочий код или ссылки на документацию.

Community 29.08.2021 10:20

Другие вопросы по теме

Похожие вопросы

Вложенные маршруты маршрутизатора React v5 с HTTP-запросом
React & Redux — обработка изменения состояния после вызова API в useEffect
Как я могу сохранить все состояния компонента в одном массиве, а затем передать его родителю?
Как отфильтровать значение, точно равное заданному входу в реагирующей таблице?
Stepper реакции-окончательной формы (форма мастера) с использованием формы машинописного текста не отображается
Как я могу протестировать событие click, которое изменяет состояние useState с помощью фермента?
Не удается прочитать свойство «путь» неопределенного при загрузке изображения на внешний интерфейс (реагировать)
Реагировать. Запускать функцию внутри onChange, только если прошло N времени без onChange
Изменить класс в зависимости от ответа API
Ошибка: слишком много повторных рендеров. React ограничивает количество рендеров, чтобы предотвратить бесконечный цикл. Не удалось найти код, вызывающий это