Внешний доступ¶
Некоторые из ваших компонентов могут нуждаться в управлении и синхронизации с системами за пределами React. Например, вам может понадобиться сфокусировать ввод с помощью API браузера, воспроизвести и поставить на паузу видеоплеер, реализованный без React, или подключиться и прослушать сообщения от удаленного сервера. В этой главе вы познакомитесь с аварийными люками, которые позволят вам "выйти за пределы" React и подключиться к внешним системам. Большая часть логики вашего приложения и потока данных не должна полагаться на эти возможности.
В этой главе
- Как "запомнить" информацию без повторного рендеринга
- Как получить доступ к элементам DOM, управляемым React
- Как синхронизировать компоненты с внешними системами
- Как удалить ненужные Эффекты из ваших компонентов
- Чем жизненный цикл Эффекта отличается от жизненного цикла компонента
- Как предотвратить повторное срабатывание эффектов от некоторых значений
- Как сделать так, чтобы эффект запускался реже
- Как разделить логику между компонентами
Ссылки на значения с помощью ссылок¶
Когда вы хотите, чтобы компонент "запомнил" некоторую информацию, но не хотите, чтобы эта информация запускала новые рендеры, вы можете использовать ref:
1 |
|
Как и состояние, ссылки сохраняются React между рендерингами. Однако установка состояния пересматривает компонент. Изменение ссылки не делает этого! Вы можете получить доступ к текущему значению ссылки через свойство ref.current
.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Ссылка - это как секретный карман вашего компонента, который React не отслеживает. Например, вы можете использовать ссылки для хранения идентификаторов таймаута, элементов DOM и других объектов, которые не влияют на вывод компонента.
Готовы изучить эту тему?
Прочитайте Ссылка на значения с помощью ссылок, чтобы узнать, как использовать ссылки для запоминания информации.
Манипулирование DOM с помощью ссылок¶
React автоматически обновляет DOM в соответствии с вашим рендерингом, поэтому вашим компонентам не часто требуется манипулировать им. Однако иногда вам может понадобиться доступ к элементам DOM, управляемым React - например, для фокусировки узла, прокрутки к нему или измерения его размера и положения. Встроенного способа сделать это в React нет, поэтому вам понадобится ссылка на узел DOM. Например, нажатие на кнопку фокусирует ввод, используя ссылку:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Готовы изучить эту тему?
Прочитайте Манипулирование DOM с помощью Refs, чтобы узнать, как получить доступ к элементам DOM, управляемым React.
Синхронизация с эффектами¶
Некоторые компоненты должны синхронизироваться с внешними системами. Например, вы можете захотеть управлять не-React компонентом на основе состояния React, установить соединение с сервером или отправить журнал аналитики, когда компонент появляется на экране. В отличие от обработчиков событий, которые позволяют вам обрабатывать определенные события, Effects позволяют вам выполнять некоторый код после рендеринга. Используйте их для синхронизации вашего компонента с системой вне React.
Нажмите Play/Pause несколько раз и посмотрите, как видеоплеер синхронизируется со значением параметра isPlaying
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
Многие эффекты также "убирают" за собой. Например, эффект, устанавливающий соединение с сервером чата, должен возвращать функцию cleanup, которая сообщает React, как отключить ваш компонент от сервера:
1 2 3 4 5 6 7 8 9 10 11 |
|
1 2 3 4 5 6 7 8 9 10 11 |
|
В процессе разработки React запускает и очищает ваш Effect еще один дополнительный раз. Вот почему вы видите, что "✅ Connecting..."
выводится дважды. Это гарантирует, что вы не забудете реализовать функцию очистки.
Готовы изучить эту тему?
Прочитайте Синхронизация с эффектами, чтобы узнать, как синхронизировать компоненты с внешними системами.
Возможно, вам не нужен эффект¶
Эффекты - это люк для выхода из парадигмы React. Они позволяют вам "выйти за пределы" React и синхронизировать ваши компоненты с какой-либо внешней системой. Если внешняя система не задействована (например, если вы хотите обновить состояние компонента при изменении некоторых пропсов или состояния), вам не нужен Эффект. Удаление ненужных Эффектов сделает ваш код более понятным, быстрым в исполнении и менее подверженным ошибкам.
Есть два распространенных случая, когда эффекты не нужны:
- Эффекты не нужны для преобразования данных для рендеринга
- Эффекты не нужны для обработки пользовательских событий
Например, вам не нужен Эффект для изменения одного состояния на основе другого состояния:
1 2 3 4 5 6 7 8 9 10 11 |
|
Вместо этого рассчитайте как можно больше во время рендеринга:
1 2 3 4 5 6 7 |
|
Тем не менее, вам нужны Эффекты для синхронизации с внешними системами.
Готовы изучить эту тему?
Прочитайте Вы можете не нуждаться в эффектах, чтобы узнать, как убрать ненужные Эффекты.
Жизненный цикл реактивных эффектов¶
Жизненный цикл эффектов отличается от жизненного цикла компонентов. Компоненты могут монтироваться, обновляться и размонтироваться. Эффект может делать только две вещи: начать синхронизировать что-то, а затем прекратить синхронизацию. Этот цикл может происходить несколько раз, если ваш Эффект зависит от пропсов и состояния, которые меняются со временем.
Этот Эффект зависит от значения пропса roomId
. пропсы - это реактивные значения, что означает, что они могут меняться при повторном рендере. Обратите внимание, что Эффект пересинхронизируется (и повторно подключается к серверу), если roomId
изменится:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
React предоставляет правило linter для проверки правильности указания зависимостей вашего Effect. Если вы забыли указать roomId
в списке зависимостей в приведенном выше примере, линтер найдет эту ошибку автоматически.
Готовы изучить эту тему?
Прочитайте Жизненный цикл реактивных событий, чтобы узнать, чем жизненный цикл эффекта отличается от жизненного цикла компонента.
Отделение событий от Эффектов¶
В разработке
Этот раздел описывает экспериментальный API, который еще не был выпущен в стабильной версии React.
Обработчики событий запускаются повторно только тогда, когда вы снова выполняете то же самое действие. В отличие от обработчиков событий, эффекты повторно синхронизируются, если любое из значений, которые они считывают, например, props или state, отличается от того, что было во время последнего рендеринга. Иногда требуется сочетание обоих типов поведения: Эффект, который повторно запускается в ответ на некоторые значения, но не на другие.
Весь код внутри Эффектов является реактивным. Он будет запущен снова, если какое-то реактивное значение, которое он считывает, изменилось в результате повторного рендеринга. Например, этот Эффект повторно подключится к чату, если изменились roomId
или theme
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Это не идеальный вариант. Вы хотите переподключиться к чату только в том случае, если roomId
изменился. Переключение theme
не должно повторно подключаться к чату! Переместите код, считывающий theme
из вашего Эффекта в Событие Эффекта:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
Код внутри событий эффектов не является реактивным, поэтому изменение темы
больше не заставит ваш эффект подключиться заново.
Готовы изучить эту тему?
Читайте Отделение событий от эффектов, чтобы узнать, как предотвратить повторное срабатывание эффектов при некоторых значениях.
Удаление зависимостей эффектов¶
Когда вы пишете Эффект, линтер проверяет, что вы включили все реактивные значения (такие как props и state), которые Эффект считывает, в список зависимостей вашего Эффекта. Это гарантирует, что ваш Эффект будет синхронизирован с последними пропсами и состоянием вашего компонента. Ненужные зависимости могут заставить ваш Эффект запускаться слишком часто или даже создать бесконечный цикл. Способ их удаления зависит от конкретного случая.
Например, этот Эффект зависит от объекта options
, который создается заново каждый раз, когда вы редактируете входные данные:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
Вы же не хотите, чтобы чат переподключался каждый раз, когда вы начинаете набирать сообщение в этом чате. Чтобы решить эту проблему, переместите создание объекта options
внутрь Эффекта, чтобы Эффект зависел только от строки roomId
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
Обратите внимание, что вы не начали с редактирования списка зависимостей, чтобы удалить зависимость options
. Это было бы неправильно. Вместо этого вы изменили окружающий код так, что зависимость стала ненужной. Думайте о списке зависимостей как о списке всех реактивных значений, используемых кодом вашего Эффекта. Вы не выбираете намеренно, что включить в этот список. Список описывает ваш код. Чтобы изменить список зависимостей, измените код.
Готовы изучить эту тему?
Читайте Удаление зависимостей эффектов, чтобы узнать, как сделать так, чтобы ваш эффект запускался реже.
Повторное использование логики с помощью пользовательских хуков¶
React поставляется со встроенными хуками, такими как useState
, useContext
и useEffect
. Иногда вам захочется иметь хук для какой-то более конкретной цели: например, для получения данных, отслеживания того, находится ли пользователь в сети, или для подключения к чату. Для этого вы можете создать собственные хуки для нужд вашего приложения.
В этом примере пользовательский хук usePointerPosition
отслеживает положение курсора, а пользовательский хук useDelayedValue
возвращает значение, которое "отстает" от переданного вами значения на определенное количество миллисекунд. Наведите курсор на область предварительного просмотра песочницы, чтобы увидеть движущийся след из точек, следующий за курсором:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Вы можете создавать пользовательские хуки, компоновать их вместе, передавать между ними данные и повторно использовать их между компонентами. По мере роста вашего приложения вы будете писать меньше эффектов вручную, потому что сможете повторно использовать уже созданные пользовательские Hooks. Существует также множество отличных пользовательских хуков, поддерживаемых сообществом React.
Готовы изучить эту тему?
Прочитайте Переиспользование логики с помощью пользовательских хуков, чтобы узнать, как обмениваться логикой между компонентами.
Что дальше?¶
Перейдите по ссылке Ссылка на значения с помощью Refs, чтобы начать читать эту главу страница за страницей!
Источник — https://react.dev/learn/escape-hatches