Я недавно начал использовать новый API React Hooks, и я нахожу его потрясающим!
Однако я столкнулся с небольшой путаницей в области зависимостей.
О чем это?
По сути, мой вариант использования довольно прост и может быть проиллюстрирован следующим псевдокодом:
import React, { useState, useCallback, useEffect } from 'react'
function Component() {
const [state, setState] = useState()
const doStuff = useCallback(() => {
// Do something
setState(result)
}, [setState])
useEffect(() => {
// Do stuff ONLY at mount time
doStuff()
}, [])
return <ExpensivePureComponent doStuff={doStuff} />
}
Теперь приведенный выше код работает нормально.
Но после того, как я установил eslint-plugin-react-hooks
, появляется предупреждение. Я должен объявить все зависимости, которые используются в моих эффектах, то есть здесь doStuff
.
Хорошо, давайте исправим этот код:
useEffect(() => {
// Do stuff ONLY at mount time
doStuff()
}, [doStuff])
Круто, больше предупреждений нет!
Подождите, без предупреждения, но ... тоже нет ошибки?
Посмотрим, о чем говорят документы useCallback
:
useCallback (fn, deps) эквивалентно useMemo (() => fn, deps)
А потом примерно useMemo
:
Вы можете положиться на использование Memo в качестве оптимизации производительности, а не в качестве семантической гарантии . В будущем React может выбрать «забыть» некоторые ранее запомненные значения и пересчитать их при следующем рендере
Так, в принципе, мой обратный вызов doStuff
, следовательно, мой useEffect
, больше не гарантированно будет работать только во время монтирования? Разве это не проблема?
Я понимаю принципы, лежащие в основе плагина eslint, но мне кажется, что существует опасная путаница между useCalback
/ useMemo
массивами зависимостей и useEffect
единицей, или я что-то упустил?
Возможно, потому что даже доктора говорят, что мой последний код в порядке:
Если по какой-то причине вы не можете переместить функцию внутри эффекта, есть еще несколько вариантов:
● ...
● В качестве последнего средства вы можете добавить функцию для воздействия на зависимости, но включить ее определение в ловушку useCallback. Это гарантирует, что он не изменится при каждом рендере, если только его собственные зависимости также не изменятся
я: бла-бла-хукс бла
SO: Какой у вас вопрос? :)
Ну, что ты думаешь? Код безопасен? Документы говорят, что это так, но также говорят, что это не так, потому что обратный вызов не гарантированно не изменится ... это немного сбивает с толку.
Есть ли плохая практика в приведенном выше псевдокоде? Когда этого не избежать, что делать? // eslint-disable-next-line