Какие варианты реализации debounce существуют в React для ограничения частоты вызова функции
Что проверяют
Понимаете ли вы, почему наивный дебаунс в React не работает, и различаете ли отложенный рендер и отложенный побочный эффект. Дальше обычно просят объяснить, что происходит с таймером при повторном рендере и как снять его при размонтировании.
Как отвечать
Начните с ловушки, специфичной именно для React: функция, созданная в теле компонента, пересоздаётся на каждом рендере. Строка const handler = debounce(fn, 300) прямо в компоненте порождает новый таймер на каждое нажатие клавиши, и дебаунса не происходит вовсе.
- дебаунс значения: свой хук, который через
useEffectиsetTimeoutоткладывает копию значения, а в функции очистки снимает таймер. Запрос вешается на отложенное значение. Самый предсказуемый способ для строки поиска; - стабильная функция:
useMemo(() => debounce(fn, 300), [])или таймер вuseRef, обязательно с вызовомcancel()при очистке эффекта. От устаревшего замыкания спасаетuseEffectEvent, стабилизированный в React 19.2, либо ref со свежим колбэком; - lodash: даёт
cancel,flushи опцииleading,trailing,maxWait. Последняя выручает, когда пользователь печатает без пауз, а показать результат надо хотя бы раз в секунду; useDeferredValue: формально не дебаунс, но часто закрывает ту же боль. Поле обновляется мгновенно, тяжёлый список отрисовывается с отставанием и прерываемо.
Обязательно скажите про гонку ответов: дебаунс сокращает число запросов, но не гарантирует, что последним придёт ответ на последний из них. Нужен AbortController или проверка актуальности по ключу запроса, в TanStack Query это решается самим ключом. Разумная задержка для поиска 250-400 мс.
Где спотыкаются
Дебаунсят само значение поля ввода. Текст начинает отставать от набора, компонент ощущается сломанным. Откладывать нужно эффект, а не отображение введённого.
Не чистят таймер при размонтировании и получают запрос, который улетает уже после ухода со страницы.
Путают дебаунс с троттлингом. Дебаунс ждёт паузы и срабатывает один раз в конце, троттлинг пропускает вызовы с фиксированной частотой. Для скролла и изменения размера окна нужен второй, а не первый.