Создание пользовательского хука 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 — локальная установка не требуется.
Все уроки этого курса
- Зачем нужны debounce и throttle в интерфейсах
- Создание пользовательского хука useDebounce
- Создание пользовательского хука useThrottle
- Практическое применение: поиск, прокрутка, изменение размера