TanStack
Getting Started

Octane Adapter

The octane-pacer adapter connects Pacer scheduling utilities to Octane state and lifecycle management. It re-exports the core package, including utility classes, stateless functions, option types, and async retrying.

Installation

shell
pnpm add @tanstack/octane-pacer

Octane requires Node.js 22.22.2 or newer and Octane 0.1.36.

Lifecycle and state

Call hooks at the top level of a compiled Octane component. The compiler assigns each call its own hook slot. The hook retains its utility across renders and commits the current callback and options in a layout effect. Selected state triggers rendering, and unmounting cleans up the utility. Use Octane 0.1.36; this package does not support the 0.2 line yet.

By default, the selected state is {}. Pass a selector to subscribe only to the fields your UI reads. The underlying store remains available for additional subscriptions.

API overview

UtilityInstance APIConvenience APIs
batchinguseBatcheruseBatchedCallback
debouncinguseDebounceruseDebouncedCallback, useDebouncedState, useDebouncedValue
queuinguseQueueruseQueuedState, useQueuedValue
rate limitinguseRateLimiteruseRateLimitedCallback, useRateLimitedState, useRateLimitedValue
throttlinguseThrottleruseThrottledCallback, useThrottledState, useThrottledValue
async batchinguseAsyncBatcheruseAsyncBatchedCallback
async debouncinguseAsyncDebounceruseAsyncDebouncedCallback
async queuinguseAsyncQueueruseAsyncQueuedState
async rate limitinguseAsyncRateLimiteruseAsyncRateLimitedCallback
async throttlinguseAsyncThrottleruseAsyncThrottledCallback

Example

This counter coalesces rapid clicks into one update after 500 ms. Flush applies the latest pending count immediately.

tsx
import { useState } from 'octane'
import { useDebouncer } from '@tanstack/octane-pacer'

export function Counter() {
  const [count, setCount] = useState(0)
  const [debouncedCount, setDebouncedCount] = useState(0)
  const debouncer = useDebouncer(setDebouncedCount, { wait: 500 }, (state) => ({
    isPending: state.isPending,
  }))
  function increment() {
    const next = count + 1
    setCount(next)
    debouncer.maybeExecute(next)
  }
  return (
    <div>
      <button onClick={increment}>Increment</button>
      <p>
        Count: {count}. Debounced: {debouncedCount}.
      </p>
      <p>Pending: {String(debouncer.state.isPending)}</p>
      <button onClick={() => debouncer.flush()}>Flush</button>
    </div>
  )
}

Child subscriptions

Use utility.Subscribe with an ordinary JSX render callback. The child subscribes to its selection without changing the utility owner's selection, and unmounting releases it.

tsx
<debouncer.Subscribe selector={(state) => ({ isPending: state.isPending })}>
  {({ isPending }) => <span>Pending: {String(isPending)}</span>}
</debouncer.Subscribe>

Use the JSX callback syntax shown here with Octane 0.1.36. Native @{...} template blocks are not supported as this component's render callback.

Reactive options

Pass a plain options object, property getters, or an options factory. The adapter evaluates top-level getters, while function-valued core options remain callbacks. Options update the existing utility; pending work, counters, and the store retain their identity.

Options retain the core partial-merge behavior. Omitting a key preserves the previous setting; explicitly passing undefined clears it. key, initialState, and initialItems initialize the utility once and do not recreate it on later updates.

Default options

Wrap descendants in PacerProvider with defaultOptions. Group defaults by utility, such as { debouncer: { leading: true } }. Local options take precedence and provider changes apply after commit.

Cleanup

Debouncers, throttlers, and batchers cancel pending timers by default. Queuers stop processing. Async variants also abort active work. Synchronous rate limiters need no timer cleanup.

Set onUnmount to replace the default cleanup, for example to call flush() before leaving a page. The callback receives the adapter instance and its selected state. If you replace cleanup for an async utility, call its cancellation or abort methods when needed.

Callback and value helpers

Callback helpers return only the scheduled function. Use an instance API when you need flush, cancel, queue controls, or state subscriptions.

State helpers return [value, setValue, utility]; value helpers return [value, utility]. Setters accept a new value or a functional update. Synchronous queue state helpers return [items, addItem, utility]. Async queue state helpers return [items, utility]; call utility.addItem() to enqueue an item.

Async utilities

The five async utilities preserve typed results and core error behavior. Use onSuccess, onError, and onSettled for outcomes, and asyncRetryerOptions for retry configuration. abort() is cooperative: your operation must observe the supplied abort signal. See the individual async guides for scheduling and concurrency details.

Devtools

Install @tanstack/devtools and @tanstack/pacer-devtools. Mount TanStackDevtoolsCore with plugins: [pacerDevtoolsPlugin()] once in your application and unmount it during cleanup. Give each utility a key to make it appear in the Pacer panel.

See the devtools setup guide for this framework's mount and cleanup code.

API reference

See the generated reference for signatures, options, and return types.