tanstack-pacer について
tanstack-pacer は、TypeScript と React アプリで関数の実行タイミングを制御する型安全なツールキットです。クラス、ファクトリー関数、React Hooks によって、デバウンス、スロットリング、レート制限、キュー、バッチ処理を提供します。
主な機能
- 01デバウンスとスロットリング
- 02時間枠によるレート制限
- 03並行数を設定できるキュー
- 04件数または時間によるバッチ処理
- 05クラス、ファクトリー関数、React Hooks
活用シーン
- 01検索入力の処理を遅延
- 02スクロール更新頻度の制限
- 03ファイルアップロードの順次処理
- 04分析イベントをまとめて送信
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ tanstack-skills/ tanstack-skills --skill tanstack-pacerインストール後、Claude Code で/tanstack-pacerを入力して読み込まれたか確認します。
詳細
概要
TanStack Pacer は、関数の実行タイミングを制御するための、統一された型安全なツールキットを提供します。デバウンス、スロットリング、レート制限、キューイング、バッチ処理のための、クラスベース API、ファクトリー関数、React フックを備えています。
コア: @tanstack/pacer
React: @tanstack/react-pacer
ステータス: ベータ
インストール
npm install @tanstack/pacer
npm install @tanstack/react-pacer # React hooks
デバウンス
一定時間操作がない状態になってから実行します。
クラス API
import { Debouncer } from '@tanstack/pacer'
const debouncer = new Debouncer(
(query: string) => fetchSearchResults(query),
{
wait: 300, // ms of inactivity before execution
leading: false, // Execute on leading edge (default: false)
trailing: true, // Execute on trailing edge (default: true)
maxWait: 1000, // Force execution after 1s of continuous calls
enabled: true,
onExecute: (result) => console.log(result),
}
)
debouncer.maybeExecute('search term')
debouncer.cancel()
debouncer.getExecutionCount()
debouncer.setOptions({ wait: 500 }) // Dynamic reconfiguration
ファクトリー関数
import { debounce } from '@tanstack/pacer'
const debouncedSearch = debounce(
(query: string) => fetchResults(query),
{ wait: 300 }
)
debouncedSearch('term')
debouncedSearch.cancel()
React フック
import {
useDebouncer,
useDebouncedCallback,
useDebouncedState,
useDebouncedValue,
} from '@tanstack/react-pacer'
// Full debouncer instance
const debouncer = useDebouncer(fn, { wait: 300 })
// Simple debounced function
const debouncedFn = useDebouncedCallback(fn, { wait: 300 })
// Debounced state management
const [debouncedValue, setValue] = useDebouncedState(initialValue, { wait: 300 })
// Debounced reactive value
const debouncedValue = useDebouncedValue(reactiveValue, { wait: 300 })
スロットリング
一定間隔ごとに最大 1 回まで実行を制限します。
クラス API
import { Throttler } from '@tanstack/pacer'
const throttler = new Throttler(
(position: { x: number; y: number }) => updatePosition(position),
{
wait: 100, // Minimum interval between executions
leading: true, // Execute immediately on first call (default: true)
trailing: true, // Execute after interval with last args (default: true)
enabled: true,
onExecute: (result) => console.log(result),
}
)
throttler.maybeExecute({ x: 100, y: 200 })
throttler.cancel()
React フック
import {
useThrottler,
useThrottledCallback,
useThrottledState,
useThrottledValue,
} from '@tanstack/react-pacer'
const throttledFn = useThrottledCallback(handleScroll, { wait: 100 })
const [throttledPos, setPos] = useThrottledState({ x: 0, y: 0 }, { wait: 100 })
レート制限
一定の時間枠内で最大実行回数を制御します。
クラス API
import { RateLimiter } from '@tanstack/pacer'
const limiter = new RateLimiter(
async (endpoint: string) => fetch(endpoint).then(r => r.json()),
{
limit: 10, // Max executions per window
window: 60000, // Time window in ms (60s)
enabled: true,
onExecute: (result) => console.log(result),
onReject: (...args) => console.warn('Rate limited:', args),
}
)
limiter.maybeExecute('/api/data') // Rejected if limit exceeded
limiter.getExecutionCount()
limiter.getRejectionCount()
React フック
import {
useRateLimiter,
useRateLimitedCallback,
useRateLimitedState,
useRateLimitedValue,
} from '@tanstack/react-pacer'
const rateLimitedFn = useRateLimitedCallback(apiCall, { limit: 5, window: 1000 })
キューイング
設定可能な同時実行数で順次実行します。
import { Queue } from '@tanstack/pacer'
const queue = new Queue({
concurrency: 1, // Max concurrent tasks
started: true, // Start processing immediately
})
queue.add(() => uploadFile(file1))
queue.add(() => uploadFile(file2))
queue.start()
queue.pause()
queue.clear()
queue.getSize() // Pending count
queue.getPending() // Currently executing count
バッチ処理
呼び出しをまとめて一括処理します。
import { Batcher } from '@tanstack/pacer'
const batcher = new Batcher(
(items: LogEntry[]) => sendBatchToServer(items),
{
maxSize: 50, // Auto-flush at 50 items
wait: 1000, // Auto-flush after 1s
}
)
batcher.add(logEntry) // Accumulates
batcher.flush() // Manual flush
batcher.getSize() // Current batch size
batcher.clear() // Discard batch
非同期バリアント
import { AsyncDebouncer, asyncDebounce, AsyncThrottler, asyncThrottle } from '@tanstack/pacer'
const asyncDebouncer = new AsyncDebouncer(
async (query: string) => {
const response = await fetch(`/api/search?q=${query}`)
return response.json()
},
{ wait: 300 }
)
// React async hooks
import { useAsyncDebouncer, useAsyncThrottler } from '@tanstack/react-pacer'
適切なユーティリティの選び方
| シナリオ | ユーティリティ | 理由 |
|---|---|---|
| 検索入力 | Debouncer | ユーザーが入力を止めるまで待機します |
| スクロールイベント | Throttler | 操作中に定期的に更新します |
| API の保護 | RateLimiter | 呼び出し頻度に厳密な上限を設けます |
| ファイルのアップロード | Queue | 順次処理します |
| 分析イベント | Batcher | 効率化のためにまとめます |
| ネットワークリクエスト | AsyncDebouncer | 中断や再試行を処理します |
先頭エッジと末尾エッジ
- 先頭(
leading: true):即座に実行し、待機時間が経過するまで後続の実行を抑制します。ボタンのクリックに適しています。 - 末尾(
trailing: true):操作が止まった後に実行します。検索入力に適しています。 - 両方:即座に実行し、最後の待機時間が経過した後にも実行します。スクロールのスロットリングに適しています。
ベストプラクティス
- デバウンスで
maxWaitを使用すると、操作が連続している間も実行を保証できます - ネットワークリクエストには非同期バリアントを使用する(中断/キャンセルを処理します)
- React フックはクリーンアップを自動で処理します。手動での破棄は不要です
- 動的な再設定には
setOptionsを使用する(例:パワーユーザー向けに待機時間を短縮する) - 複雑なシナリオではユーティリティを組み合わせる(レート制限付きキューなど)
- レート制限に達したときユーザーに知らせるには、RateLimiter で
onRejectを使用する
よくある落とし穴
- スロットリングが必要な場面でデバウンスを使用する(デバウンスは操作がない状態になるまで待機しますが、スロットリングは定期的な実行を保証します)
- 長時間続くイベントで、デバウンスに
maxWaitを指定しない - レンダリングのたびに新しいインスタンスを作成する(フックまたはモジュールレベルのインスタンスを使用してください)
- React 以外の環境でクリーンアップを忘れる(
cancel()を呼び出してください)
コメント
Markdown 対応