Реагируйте на крючки с ворсом: всегда ли это имеет смысл? - PullRequest
2 голосов
/ 18 мая 2019

Как вы, вероятно, знаете, create-реагировать на приложение 3 поставляется с новым правилом eslint: react-hooks/exhaustive-deps. Когда в массиве зависимостей ловушки отсутствует зависимость, отображается предупреждение. Но это не всегда имеет смысл.

Некоторые зависимости могут быть «тихими» или «слабыми» зависимостями.

В коде у меня есть следующий случай:

const Project = ({ id, '*': tab }) => {
  const [{ openProjects }, { openProject, setProjectTab }] = useStore()

  useLayoutEffect(() => {
    if(find(openProjects, { id }))
      setProjectTab(id, tab)
    else openProject(id, tab)
  }, [tab])

  return (...)
}

, что дает мне:

Строка 98: React Hook useLayoutEffect не имеет зависимостей: 'id', 'openProject', 'openProjects' и 'SetProjectTab. Либо включите их, либо удалите массив зависимостей реагирующие-крюки / исчерпывающий-Deps

openProject и setProjectTab являются постоянными функциями, они всегда указывают на одни и те же ссылки, поэтому я мог бы включить их в массив для сокращения предупреждения. Нет проблем.

Но openProjects - это массив из моего глобального состояния, который обрабатывается как в redux: каждый раз, когда происходит обновление, создается новый массив.

Но , это обновление в точности происходит как эффект , который создал бы бесконечный цикл обновления, если бы я добавил его в качестве зависимости.

Итак:

  • Соблюдение правила линтера: бесконечный цикл.
  • Не подчиняется правилу линтера: раздражающее предупреждение.

Я ошибаюсь в своем дизайне или exhaustive-deps действительно слишком ограничен и должен учитывать концепцию слабых зависимостей (т. Е. не не вызывает эффект при изменении)?

Ответы [ 2 ]

1 голос
/ 19 мая 2019

Если какой-либо эффект зависит от результата какого-либо вычисления, например, find(openProjects, { id }), но не на аргументах для этого вычисления, тогда возможно сделать его явно зависимым только от результата этого вычисления, например, извлекая переменную:

const isFound = find(openProjects, { id })

useLayoutEffect(() => {
  if(isFound)
    setProjectTab(id, tab)
  else openProject(id, tab)
}, [isFound, setProjectTab, openProject, id, tab])

Я бы рекомендовал оставить правило eslint включенным и подумать о минимальном наборе всех зависимостей , которые могут повлиять на результаты выполнения кода.

1 голос
/ 19 мая 2019

У меня возникла такая же проблема.Когда я использую хуки, я включаю только переменные, которые изменяются в массиве зависимостей, я не включаю константы или данные, которые, как я знаю, не меняются.

Вы можете использовать // eslint-disable-next-line react-hooks / exhaustive-deps, чтобы отключить линтинг для следующеголиния.

...