TanStack Router предоставляет гибкие инструменты для управления навигацией в приложении на JavaScript. Одной из ключевых задач при работе с роутером является контроль частоты вызовов навигационных действий, чтобы избежать лишних перерисовок, гонок состояния или избыточных запросов к серверу. В этом контексте активно применяются throttling и debouncing.
Throttling — это ограничение частоты вызова функции. При использовании throttling функция может выполняться не чаще чем один раз за заданный интервал времени, даже если событие вызывается чаще.
Debouncing — это задержка выполнения функции до момента, когда событие прекращает происходить в течение заданного времени. Функция выполняется только один раз после того, как поток событий завершился.
В контексте TanStack Router это означает:
Для throttling навигации можно использовать сторонние утилиты вроде
lodash.throttle или встроенные механизмы JavaScript через
setTimeout и Date.now. Основная идея
заключается в обёртывании функции router.navigate:
import { Router } from '@tanstack/router'
import throttle from 'lodash.throttle'
const router = new Router({/* конфигурация роутера */})
const throttledNavigate = throttle((to) => {
router.navigate(to)
}, 300) // 300 мс интервал между вызовами
// Использование
throttledNavigate('/dashboard')
throttledNavigate('/profile') // будет проигнорирован, если прошло меньше 300 мс
Ключевой момент: Throttling особенно актуален для событий, которые могут срабатывать очень часто — прокрутка, изменение размеров окна, ввод текста в реальном времени, автоподгрузка контента с навигацией.
Debouncing позволяет дождаться «спокойного» состояния приложения перед навигацией. Например, при поиске в списке и необходимости менять маршрут только после завершения ввода пользователя:
import { Router } from '@tanstack/router'
import debounce from 'lodash.debounce'
const router = new Router({/* конфигурация роутера */})
const debouncedNavigate = debounce((to) => {
router.navigate(to)
}, 500) // навигация произойдёт через 500 мс после последнего события
// Использование
const handleSearchInput = (event) => {
const query = event.target.value
debouncedNavigate(`/search?q=${encodeURIComponent(query)}`)
}
Ключевой момент: Debouncing помогает снизить нагрузку на сервер и избежать лишних переходов, когда пользователь вводит данные слишком быстро.
TanStack Router предоставляет хуки, которые интегрируются с
throttling и debouncing. Например, useNavigate возвращает
функцию навигации, которую можно обернуть:
import { useNavigate } from '@tanstack/router'
import { useCallback } from 'react'
import debounce from 'lodash.debounce'
function SearchComponent() {
const navigate = useNavigate()
const debouncedNavigate = useCallback(
debounce((query) => {
navigate(`/search?q=${encodeURIComponent(query)}`)
}, 400),
[navigate]
)
const handleChange = (e) => {
debouncedNavigate(e.target.value)
}
return
}
Важно: Использование useCallback
обеспечивает сохранение одной версии функции между рендерами,
предотвращая постоянное создание новых обёрток и лишние перерисовки.
Иногда необходимо комбинировать оба подхода, особенно при сложной навигации, где есть быстрые события и длительные действия пользователя:
Пример:
const navigateThrottledDebounced = throttle(
debounce((to) => router.navigate(to), 300),
100
)
В таком случае:
debounce гарантирует, что навигация сработает
только после 300 мс «покоя» пользователя.throttle ограничивает общую частоту вызовов до одного
действия каждые 100 мс, предотвращая коллизии в высокочастотных
сценариях.state и params маршрутов — иногда необходимо
сохранять последний intended путь, чтобы избежать пропуска
навигации.useCallback или useMemo для мемоизации
функций, чтобы не терять эффект throttling/debouncing при
ререндере.