В этом году я довольно часто использовал хуки, наряду с хуками redux, в личных и производственных проектах. API немного грубоват, но в целом они соответствуют шумихе. Мне удалось относительно легко реорганизовать приложения, и сделать все компоненты работоспособными действительно очень здорово.

Дэн Абрамов написал чертовски длинный и полезный пост в блоге на тему useEffect пару месяцев назад (я опаздываю на вечеринку ik ik). Я сосредоточен здесь не на TL; DR (у него есть собственное резюме) и даже не на моих собственных выводах из статьи, а на некоторых интересных вариантах поведения API хуков, которые я не уловил в документации или учебных пособиях, которые у меня были. читать. Они были своего рода примечанием к статье Дэна, но, учитывая, насколько чужды мне эти идеи, я думаю, что они достойны хотя бы небольшого поста, подобного этому.

cleanupCallback! = componentDidUnmount

Первый связан с необязательной функцией очистки, которую вы можете вернуть из обратного вызова, переданного в useEffect. Из официальных документов реакции:

Когда именно React очищает эффект? React выполняет очистку при отключении компонента. Однако, как мы узнали ранее, эффекты запускаются для каждого рендера, а не только один раз. Вот почему React также очищает эффекты от предыдущего рендеринга, прежде чем запускать эффекты в следующий раз.

Думаю, как только я прочитал, что он запускается при отключении компонента, мой мозг проигнорировал остальную часть этого утверждения. Я был настолько привязан к жизненному циклу и тому, что классы == хуки, я не осознавал новаторскую функцию useEffect - запускать его очистку каждый раз, когда обратный вызов useEffect запускается снова. Каждый раз, когда выполняется обратный вызов useEffect, прежде чем его можно будет запустить снова, будет запущен обратный вызов очистки. Это имеет некоторые интересные последствия, хотя, честно говоря, в настоящий момент на ум не приходит никакого практического применения такого поведения 😅.

Обратный вызов эффекта будет запускаться после каждого рендеринга, если мы не укажем массив зависимостей. Если мы укажем deps, он будет запускаться только тогда, когда этот dep изменяется между рендерами. И если это произойдет, обратный вызов очистки также должен будет выполняться. Это происходит не только при отключении компонента. Но на самом деле нам, вероятно, следует думать не о нашем компоненте как о «размонтируемом» с компонентом хуков, а как о конце просто другого, хотя и окончательного, рендеринга.

В этом можно убедиться, поиграв с этим примером. Проверьте консоль, и вы увидите, что при каждом нажатии кнопки печатается журнал обратного вызова, а также журнал функции очистки.

dispatch крутой хак

Дэн создал пример эффекта, который использует две переменные состояния. Расчетное значение одной из переменных зависит от другой, поэтому другие переменные должны быть указаны как зависимые. Подробно вы можете увидеть это на его примере здесь или просто взглянуть на фрагмент ниже.

В приведенном выше примере мы используем обратный вызов для изменения значений count, что позволяет нам не передавать его в наш массив deps. Но поскольку его вычисленное значение зависит от step, мы должны передать step в массив. Следствием этого является то, что при изменении step вызываются как обратный вызов эффекта, так и функции очистки. Если по какой-то причине вам не нужен эффект и функция очистки вызывается в любое время, вы можете вызвать dispatch.

dispatch в эффекте - это что-то вроде удаленного доступа к вашему состоянию и его изменения. dispatch отправляет действие изнутри эффекта соответствующему reducer, отделяя эффект от состояния и позволяя вам более точно контролировать, когда ваш эффект запускается. Пример можно найти здесь.

На самом деле это был главный момент, который пытался донести Абрамов, но я включил его сюда, потому что такое поведение dispatch не очевидно из официальных документов. Я также хотел включить его, потому что он показывает полезность useReducer. Когда я впервые ознакомился с документацией по этому методу, я был немного разочарован. Я считал, что это просто глобальный редуктор в стиле редукции, переведенный в состояние компонента. Теперь я вижу, что у него немного больше возможностей.

Хотя это были моменты, которые меня потрясли, в статье Дэна есть много других очень полезных моментов, и, хотя она длинная, я призываю всех ее прочитать или, по крайней мере, TL; DR. Большая часть статьи поощряет адаптацию новой ментальной модели для фаз рендеринга, и хотя я не могу сказать, что у меня получилось на 100%, я скажу, что это мне очень помогло.

Еще один, более пикантный вывод - API хуков может потребоваться немного доработки и абстракции перед переходом в прайм-тайм, особенно в районе useEffect. Мемоизация функций, вывод статических функций за пределы тела компонента, создание длинных редукторов создает некоторые барьеры для входа в imo. Или, может быть, я просто ограничен в своих мыслях и не вижу ничего правильного. Будем болтать в комментариях!

🐈