Дебаунсинг функции в React: оптимальное применение debounce()

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

JS
Скопировать код
function debounce(func, delay) {
  let timeoutId;
  
  return function executedFunction(...args) {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(this, args), delay);
  };
}

const debouncedSearch = debounce(() => {
  // Выполнение поисковых операций
}, 300);

document.getElementById('search-input').addEventListener('input', debouncedSearch);

Функция debounce отсрочит выполнение переданной ей функции func до момента, когда пройдет заданное число миллисекунд delay с момента её последнего вызова. Применяйте её для оптимизации обработки таких часто срабатывающих событий, как input или resize.

Кинга Идем в IT: пошаговый план для смены профессии

Применение debounce в React: совместимость с хуками и асинхронностью

Обогатите свои React-приложения, эффективно используя debounce.

Применение useCallback для создания запоминающихся функций с debounce

Внедряйте запоминающиеся функции при помощи хука useCallback:

JS
Скопировать код
const handleSearch = useCallback(
  debounce((searchValue) => {
    // Поисковый запрос
  }, 300),
  [] // Пустой массив зависимостей для однократной инициализации
);

Для сочетания debounce с побочными эффектами в функциональных компонентах используйте useEffect, чтобы функции срабатывали в правильный момент жизненного цикла компонента.

Реакция на изменения: обновление компонентов с контролируемым вводом

Для компонентов с контролируемым состоянием важно быть способными обновлять состояние без задержек:

JS
Скопировать код
const [searchValue, setSearchValue] = useState('');

const debouncedSetSearchValue = debounce(setSearchValue, 300);

const handleValueChange = (event) => {
  event.persist();  // Для сохранения события в React
  debouncedSetSearchValue(event.target.value);
};

Применение debounce с потоками данных

При работе с потоками данных отлично подойдет Observable, например, из библиотеки RxJS:

JS
Скопировать код
const searchStream = new Rx.Subject();
const debouncedSearchStream = searchStream.pipe(
  debounceTime(300)
);

debouncedSearchStream.subscribe((searchTerm) => {
  // Вызов API с полученной информацией
});

const handleValueChange = (event) => {
  searchStream.next(event.target.value);
};

Визуализация

Представьте, что вы находитесь на оживлённой железнодорожной станции, где в качестве метафоры для ввода данных используются поезда:

Markdown
Скопировать код
🚂💨 = Ввод данных
🚉 = Станция debounce
⏲️ = Таймер (задержка debounce)

Задача начальника станции — debounce:

Markdown
Скопировать код
До: 🚂💨🚂💨🚂💨 – Час пик, хаос
После: 🚉 + ⏲️  = 🚂💨.......🚂💨.......🚂💨 – Порядок и вступление в ритм

Суть: Начальник станции контролирует время ⏲️ и отправляет поезд только тогда, когда новый не прибывает в пределах этого времени.

Продвинутый Debounce: как стать мастером

Чтобы успешно работать с debounce, уделите внимание нескольких дополнительным аспектам.

SyntheticEvent.persist() при обработке событий в React

В React используйте .persist() при работе с SyntheticEvent для сохранения данных события во время асинхронной задержки, что важно при применении debounce.

Управление асинхронными операциями

Асинхронный подход гарантирует, что будет выполнено только последнее обещание:

JS
Скопировать код
import AwesomeDebouncePromise from 'awesome-debounce-promise';

const apiSearch = (query) => {
  // Асинхронный запрос к API
};

const debouncedApiSearch = AwesomeDebouncePromise(apiSearch, 300);

Оформление побочных эффектов в функциональных компонентах

Для интеграции побочных эффектов от debounce-действий используйте useEffect. Это позволит поддерживать реактивность компонентов.

Создание переиспользуемых хуков

Разработка пользовательских хуков, таких как useDebouncedValue или useDebouncedCallback, позволяет инкапсулировать логику debounce для последующего использования:

JS
Скопировать код
function useDebouncedValue(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(timer);  // Освобождаем таймер
    };
  }, [value, delay]);

  return debouncedValue;
}

Полезные материалы

  1. Описание и примеры использования debounce — исчерпывающие разъяснения на MDN.
  2. Debouncing и Throttling — разница между debounce и throttle с примерами на сайте CSS-Tricks.
  3. Документация Lodash — официальное руководство по использованию debounce от Lodash.
  4. Простое руководство по созданию debounce функции от Дэвида Уолша.
  5. Дебаты о разнице между debounce и throttle — обсуждение на Stack Overflow.
  6. Универсальный код debounce для JavaScript на GitHub Gist.
  7. Цикл событий JavaScript: микрозадачи и макрозадачи — статья для понимания работы event loop в JavaScript.
Свежие материалы