tanstack-pacer
8
总安装量
8
周安装量
#34601
全站排名
安装命令
npx skills add https://github.com/fellipeutaka/leon --skill tanstack-pacer
Agent 安装分布
opencode
8
gemini-cli
8
claude-code
8
github-copilot
8
codex
8
kimi-cli
8
Skill 文档
TanStack Pacer
Version: @tanstack/react-pacer@latest Requires: React 16.8+, TypeScript recommended
Quick Setup
npm install @tanstack/react-pacer
import { useDebouncedCallback } from '@tanstack/react-pacer'
function SearchInput() {
const debouncedSearch = useDebouncedCallback(
(query: string) => fetchResults(query),
{ wait: 300 },
)
return <input onChange={(e) => debouncedSearch(e.target.value)} />
}
4 Hook Variants Per Utility
Each utility (Debouncer, Throttler, RateLimiter, Queuer, Batcher) provides 4 React hooks:
| Hook | Returns | Use Case |
|---|---|---|
use[Utility] |
Instance | Full control, custom state subscriptions |
use[Utility]Callback |
Wrapped function | Simple event handler wrapping |
use[Utility]State |
[value, setValue, instance] |
Debounced/throttled React state |
use[Utility]Value |
[derivedValue, instance] |
Read-only derived value from props/state |
PacerProvider (Optional)
import { PacerProvider } from '@tanstack/react-pacer'
<PacerProvider
defaultOptions={{
debouncer: { wait: 300 },
throttler: { wait: 200 },
}}
>
<App />
</PacerProvider>
Devtools
npm install -D @tanstack/react-devtools @tanstack/react-pacer-devtools
import { TanStackDevtools } from '@tanstack/react-devtools'
import { pacerDevtoolsPlugin } from '@tanstack/react-pacer-devtools'
<TanStackDevtools plugins={[pacerDevtoolsPlugin()]} />
Utilities must have a key option to appear in devtools.
Rule Categories
| Priority | Category | Rule File | Impact |
|---|---|---|---|
| CRITICAL | Hook Selection | rules/hook-selection.md |
Correct hook choice per use case |
| CRITICAL | Debouncing | rules/deb-debouncing.md |
Prevents wasted API calls and flickering UI |
| HIGH | Throttling | rules/thr-throttling.md |
Smooth, evenly-spaced execution |
| HIGH | State & Reactivity | rules/state-reactivity.md |
Prevents unnecessary re-renders |
| HIGH | Async Patterns | rules/async-patterns.md |
Correct async execution with retry, abort, error handling |
| MEDIUM | Rate Limiting | rules/rl-rate-limiting.md |
Enforces execution budgets |
| MEDIUM | Queuing | rules/que-queuing.md |
Lossless ordered/priority task processing |
| MEDIUM | Batching | rules/bat-batching.md |
Groups operations for bulk processing |
| LOW | Configuration | rules/config-options.md |
Dynamic options, providers, shared config |
| LOW | Devtools | rules/devtools.md |
Debugging and monitoring utilities |
Critical Rules
Always Do
- Use hooks over function wrappers â
useDebouncedCallbacknotdebounce()for proper React lifecycle - Choose the right hook variant â
useCallbackfor event handlers,useStatefor controlled inputs,useValuefor derived values - Opt-in to state subscriptions â pass selector as 3rd arg:
useDebouncer(fn, opts, (s) => ({ isPending: s.isPending })) - Use async variants for API calls â
useAsyncDebouncedCallbackgives error handling, retry, abort - Pass
AbortSignalto fetch âgetAbortSignal()enables cancellation of in-flight requests - Use
keyoption for devtools â only keyed utilities appear in devtools panel
Never Do
- Subscribe to all state â omit selector or use instance directly to avoid re-renders on every state change
- Use debouncing when you need guaranteed execution â use throttling or queuing instead
- Use rate limiting for evenly-spaced calls â rate limiting is bursty; use throttling for smooth spacing
- Use
debounce()function in React â no lifecycle cleanup; useuseDebouncedCallbackhook instead - Expect
maxWaiton Debouncer â Pacer has nomaxWait; use Throttler for guaranteed periodic execution
Key Patterns
// Debounced search input with state
import { useDebouncedState } from '@tanstack/react-pacer'
function Search() {
const [query, setQuery, debouncer] = useDebouncedState('', { wait: 300 })
// query updates after 300ms pause; setQuery is immediate
return <input onChange={(e) => setQuery(e.target.value)} />
}
// Async debounced API call with abort
import { useAsyncDebouncedCallback } from '@tanstack/react-pacer'
function AsyncSearch() {
const search = useAsyncDebouncedCallback(
async (query: string) => {
const signal = search.getAbortSignal()
const res = await fetch(`/api/search?q=${query}`, { signal })
return res.json()
},
{ wait: 300, onSuccess: (data) => setResults(data) },
)
return <input onChange={(e) => search(e.target.value)} />
}
// Throttled scroll handler
import { useThrottledCallback } from '@tanstack/react-pacer'
function ScrollTracker() {
const onScroll = useThrottledCallback(
() => trackScrollPosition(window.scrollY),
{ wait: 100 },
)
useEffect(() => {
window.addEventListener('scroll', onScroll)
return () => window.removeEventListener('scroll', onScroll)
}, [onScroll])
}
// Derived debounced value from props
import { useDebouncedValue } from '@tanstack/react-pacer'
function FilteredList({ filter }: { filter: string }) {
const [debouncedFilter] = useDebouncedValue(filter, { wait: 300 })
return <ExpensiveList filter={debouncedFilter} />
}
// Async queue with concurrency
import { useAsyncQueuer } from '@tanstack/react-pacer'
function UploadQueue() {
const queuer = useAsyncQueuer(uploadFile, { concurrency: 3 })
return <button onClick={() => queuer.addItem(file)}>Upload</button>
}