0Pricing
React Academy · Урок

Создание пользовательского хука useDebounce

Создайте хук useDebounce, откладывающий обновление состояния, пока пользователь не перестанет печатать

«Создание пользовательского хука useDebounce» — бесплатный урок React Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения React Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс React Academy содержит 4 уроков всего.

Сигнатура хука

Хук useDebounce принимает значение и задержку в миллисекундах, а возвращает отложенную версию этого значения: function useDebounce(value, delay). Возвращаемое debouncedValue отстаёт от текущего значения и обновляется только после того, как указанная задержка истекла без новых изменений.

Внутреннее состояние debouncedValue

Внутри хука объявите переменную состояния: const [debouncedValue, setDebouncedValue] = useState(value). Это состояние хранит последнее подтверждённое значение. Изначально оно равно начальному значению и обновляется только после срабатывания таймера отложенного вызова. Компоненты, считывающие debouncedValue, получают стабильное, окончательно установленное значение ввода.

useEffect с setTimeout

Основная логика находится в useEffect: создайте таймер с помощью setTimeout(() => setDebouncedValue(value), delay) и сохраните его идентификатор. Эффект выполняется при каждом изменении value или delay. Таймер срабатывает через delay миллисекунд после последнего изменения и обновляет состояние отложенного значения.

Отмена таймера в функции очистки

Функция очистки useEffect вызывает clearTimeout(timerId). Когда value меняется до срабатывания таймера, React запускает очистку, отменяя ожидающее обновление. Затем планируется новый таймер. Это основной механизм работы отложенного вызова: быстрые изменения постоянно сбрасывают таймер.

Зависимости эффекта

Массив зависимостей useEffect должен содержать [value, delay]. Эффект запускается заново при изменении входного значения, поэтому планируется новый таймер, а также при изменении задержки, если вызывающий код динамически корректирует интервал отложенного вызова. Оба значения необходимо включить, чтобы избежать проблем с устаревшими замыканиями.

Использование хука в компоненте

Использование несложно: const debouncedSearch = useDebounce(searchInput, 300). Отдельный useEffect с [debouncedSearch] в списке зависимостей выполняет сетевой запрос. Состояние ввода (searchInput) обновляется сразу, поэтому поле остаётся отзывчивым; ожидать нужно только сетевому запросу.

Особый случай: немедленный первый вызов

По умолчанию стандартная реализация выполняется только на завершающем этапе. Для режима «немедленного выполнения», который вызывает функцию при первом срабатывании, но применяет отложенный вызов к последующим, нужна ссылка для отслеживания того, был ли уже выполнен вызов, и её сброса после задержки. Это сложнее, но полезно для кнопок отправки.

Обобщённый параметр типа TypeScript

Сделайте хук обобщённым для обеспечения безопасности типов: function useDebounce(value: T, delay: number): T. Это позволяет TypeScript вывести тип debouncedValue из типа value. Обобщённый параметр T автоматически передаётся во внутреннее состояние и возвращаемый тип.

Распространённая ошибка: отсутствие очистки

Частая ошибка — забыть вернуть функцию очистки из useEffect. Без очистки каждое изменение значения создаёт новый таймер, но никогда не отменяет старый. В результате срабатывают несколько таймеров, из-за чего setDebouncedValue вызывается несколько раз с устаревшими значениями, полностью лишая отложенный вызов смысла.

Сравнение с подходами на основе useRef

Другой вариант — хранить саму функцию отложенного вызова в useRef с помощью lodash. В отличие от подхода на основе состояния, подход с объектом ссылки откладывает вызовы функций, а не значения. Используйте хук на основе состояния, когда нужно производное значение; используйте подход с функцией обратного вызова, когда нужно отложить обработчик события.

Проверка фактического поведения

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

Очистка useEffect в useDebounce

Почему useEffect в useDebounce должен возвращать функцию очистки, вызывающую clearTimeout?

Итоги урока: хук useDebounce

Хук useDebounce(value, delay) хранит состояние отложенного значения, которое обновляется только после delay мс тишины. Его useEffect устанавливает таймер и очищает его при очистке, отменяя устаревшие таймеры. Используйте отложенное значение как зависимость эффектов, выполняющих получение данных с сервера. Добавьте обобщённый параметр TypeScript для полной безопасности типов.

Часто задаваемые вопросы

Урок «Создание пользовательского хука useDebounce» бесплатный?

Да — полный текст урока «Создание пользовательского хука useDebounce» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс React Academy, подпишись на CoddyKit PRO. Курс React Academy содержит 4 уроков всего.

Чему я научусь в уроке «Создание пользовательского хука useDebounce»?

Создайте хук useDebounce, откладывающий обновление состояния, пока пользователь не перестанет печатать Ты практикуешь React Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать React Academy?

Предыдущий опыт не требуется. React Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Создание пользовательского хука useDebounce»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке React Academy?

Да. Каждый урок React Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Зачем нужны debounce и throttle в интерфейсах
  2. Создание пользовательского хука useDebounce
  3. Создание пользовательского хука useThrottle
  4. Практическое применение: поиск, прокрутка, изменение размера
← Назад к React Academy