Передача функций в компоненты¶
Как передать обработчик события (например, onClick) компоненту?¶
Передавайте обработчики событий и другие функции через пропсы дочерним компонентам:
1 |
|
Если вы хотите иметь доступ к компоненту-родителю через обработчик, вам нужно привязать функцию к экземпляру компонента (см. ниже).
Как привязать функцию к экземпляру компонента?¶
В зависимости от того, какой синтаксис и подход к созданию компонентов вы используете, существует несколько способов удостовериться, что функции имеют доступ к таким атрибутам компонента, как this.props
и this.state
.
Привязка в конструкторе (ES2015)¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Привязка в свойствах класса (предложение-кандидат)¶
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Привязка в методе render()¶
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Примечание:
Использование
Function.prototype.bind
в render() создаёт новую функцию при каждом рендере компонента, что может повлиять на производительность (см. ниже).
Стрелочная функция в render()¶
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Примечание:
Использование стрелочной функции в render() создаёт новую функцию при каждой отрисовке компонента, что может нарушать оптимизации, использующие строгое сравнение для определения идентичности.
Можно ли использовать стрелочные функции в методе render()?¶
В целом, да. Зачастую это самый простой способ передать параметры через колбэки.
Если же у вас возникли проблемы с производительностью — оптимизируйте!
Зачем вообще нужна привязка?¶
В JavaScript эти два фрагмента кода не равнозначны:
1 |
|
1 2 |
|
Привязка гарантирует, что второй фрагмент будет работать так же, как и первый.
В React, как правило, привязывать нужно только те методы, которые вы хотите передать другим компонентам. Например, <button onClick={this.handleClick}>
передаёт this.handleClick
, поэтому его нужно привязать. Впрочем, метод render
и методы жизненного цикла привязывать не обязательно, так как мы не передаём их в другие компоненты.
Ознакомьтесь со статьёй Йехуды Катц, в которой более подробно объяснено, что такое привязка, и как работают функции в JavaScript.
Почему моя функция вызывается каждый раз при отрисовке компонента?¶
Убедитесь, что вы не вызываете функцию, когда передаёте её компоненту:
1 2 3 4 |
|
Вместо этого передайте саму функцию (без скобок):
1 2 3 4 |
|
Как передать параметры обработчику событий или колбэку?¶
Чтобы передать параметры обработчику событий, оберните его в стрелочную функцию:
1 |
|
Это действие равносильно использованию .bind
:
1 |
|
Пример: Передача параметров с использованием стрелочных функций¶
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 |
|
Пример: Передача параметров с использованием атрибутов данных¶
В качестве альтернативного подхода вы можете использовать DOM API, чтобы хранить необходимые для обработчиков событий данные. Рассмотрите этот подход, если вам нужно оптимизировать большое количество элементов или использовать дерево визуализации, полагающееся на компонент React.PureComponent для проверки на равенство.
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 |
|
Как предотвратить слишком быстрый или слишком частый вызов функции?¶
Если вы используете обработчики событий, такие как onClick
или onScroll
, и хотите предотвратить быстрое срабатывание колбэков, вы можете ограничить скорость выполнения колбэка. Для этого вы можете использовать:
- троттлинг: выборочные изменения, зависимые от частоты, основанной на времени (напр.
_.throttle
) - дебаунсинг: изменения, задействованные после некого периода бездействия (напр.
_.debounce
) - троттлинг с помощью
requestAnimationFrame
: выборочные изменения, основанные наrequestAnimationFrame
(напр.raf-schd
)
Взгляните на визуализацию, которая сравнивает функции throttle
и debounce
.
Примечание:
_.debounce
,_.throttle
иraf-schd
предусматривают методcancel
для отмены отложенных колбэков. Вы должны либо вызвать этот метод из componentWillUnmount, либо удостовериться, что компонент всё ещё встроен в пределах отложенной функции.
Throttle¶
Троттлинг предотвращает повторный вызов функции в заданный период времени. Этот метод был задействован в примере ниже, чтобы не допустить вызов обработчика "click" чаще чем раз в секунду.
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 |
|
Debounce¶
Дебаунсинг гарантирует, что функция не будет выполняться до тех пор, пока не пройдёт определённое количество времени с момента её последнего вызова. Этот метод пригодится, если вам нужно провести ресурсоёмкий расчёт в ответ на событие, которое может быстро повториться (например, прокрутка страницы или нажатие клавиш). В примере ниже для ввода текста используется задержка в 250 мс.
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 |
|
requestAnimationFrame
throttling¶
requestAnimationFrame
— это способ организации очереди функции, которая будет выполнена в браузере за оптимальное время для производительности отрисовки. Функция, поставленная в очередь с помощью requestAnimationFrame
, запустится в следующем кадре. Браузер приложит все усилия, чтобы обеспечить 60 кадров в секунду (60 fps — frames per second). Однако, если браузер не в состоянии справиться с этой задачей, он естественным образом ограничит количество кадров в секунду. Например, если ваше устройство поддерживает только 30 fps, то и получите вы только 30 кадров. Использование requestAnimationFrame
для троттлинга является очень полезным методом, так как помогает предотвратить выполнение более 60 обновлений в секунду. Если вы выполняете 100 обновлений в секунду, это создаёт лишнюю работу для браузера, которую пользователь всё равно не заметит.
Примечание:
Использование этой техники захватит только последнее опубликованное значение в кадре. Пример работы данной оптимизации вы можете увидеть на
MDN
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 |
|
Тестирование ограничения скорости¶
Когда вы тестируете, что ваш код ограничения скорости работает правильно, полезно иметь возможность прокрутить время. Если вы используете jest
, вам может пригодиться mock timers
. Если вы используете requestAnimationFrame
, то raf-stub
может оказаться полезным инструментом для управления смены кадров анимации.