Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
d634f62
start on retry feature
KevinVandy Aug 5, 2025
d03fe2b
add retry example
KevinVandy Aug 6, 2025
631c6e0
Merge branch 'main' into retry
KevinVandy Aug 7, 2025
338db04
aborts through async-retryer only
KevinVandy Aug 10, 2025
0f16e6c
add an optional pacer provider
KevinVandy Aug 10, 2025
3b86df9
add providers to main examples
KevinVandy Aug 11, 2025
a594529
feat: add initial setup for devtools
AlemTuzlak Aug 11, 2025
4584821
ci: apply automated fixes
autofix-ci[bot] Aug 11, 2025
9b63459
chore: fix test issues
AlemTuzlak Aug 11, 2025
13c12a2
chore: merge fix
AlemTuzlak Aug 11, 2025
c60e383
ci: apply automated fixes
autofix-ci[bot] Aug 11, 2025
a8f5096
chore:fix render issue
AlemTuzlak Aug 11, 2025
7badb9f
ci: apply automated fixes
autofix-ci[bot] Aug 11, 2025
db96874
ci: apply automated fixes
autofix-ci[bot] Aug 11, 2025
c102954
feat: drastically improve the pacer devtools UI
AlemTuzlak Aug 12, 2025
03fe008
ci: apply automated fixes
autofix-ci[bot] Aug 12, 2025
b220c67
chore: remove built-in tree in favor of devtools/ui
AlemTuzlak Aug 12, 2025
99d052b
ci: apply automated fixes
autofix-ci[bot] Aug 12, 2025
b1eb9e6
refactor to key
KevinVandy Aug 12, 2025
c7699df
ci: apply automated fixes
autofix-ci[bot] Aug 12, 2025
5df992f
rename devtool packages to be consistent with query devtool package n…
KevinVandy Aug 13, 2025
c145ad1
fix sherif
KevinVandy Aug 13, 2025
548caf5
separate left and right panels of devtools
KevinVandy Aug 13, 2025
f1cee1c
denser ui
KevinVandy Aug 13, 2025
57966f6
better right panel, emit entire instance
KevinVandy Aug 13, 2025
dd527a0
add some action buttons to devtools that kind of work
KevinVandy Aug 13, 2025
f088dc8
event bus goes both ways
KevinVandy Aug 14, 2025
7e853c0
all utils listen to devtools
KevinVandy Aug 15, 2025
8984c3d
Merge branch 'feat/add-devtools-to-pacer' into retry
KevinVandy Aug 15, 2025
2a50176
remove console log
KevinVandy Aug 15, 2025
185aa09
Merge branch 'feat/add-devtools-to-pacer' into retry
KevinVandy Aug 15, 2025
fa451f3
ci: apply automated fixes
autofix-ci[bot] Aug 15, 2025
75414d2
sync package versions
KevinVandy Aug 15, 2025
5c5d6c9
ci: apply automated fixes
autofix-ci[bot] Aug 15, 2025
6b372da
break up devtools components
KevinVandy Aug 16, 2025
5a72798
Merge branch 'feat/add-devtools-to-pacer' into retry
KevinVandy Aug 17, 2025
05a046a
default options
KevinVandy Aug 18, 2025
e42387e
ci: apply automated fixes
autofix-ci[bot] Aug 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions docs/framework/react/reference/functions/pacerprovider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
id: PacerProvider
title: PacerProvider
---

<!-- DO NOT EDIT: this page is autogenerated from the type comments -->

# Function: PacerProvider()

```ts
function PacerProvider(__namedParameters): Element
```

Defined in: [react-pacer/src/provider/PacerProvider.tsx:43](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/provider/PacerProvider.tsx#L43)

## Parameters

### \_\_namedParameters

[`PacerProviderProps`](../../interfaces/pacerproviderprops.md)

## Returns

`Element`
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function useAsyncBatcher<TValue, TSelected>(
selector): ReactAsyncBatcher<TValue, TSelected>
```

Defined in: [react-pacer/src/async-batcher/useAsyncBatcher.ts:167](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-batcher/useAsyncBatcher.ts#L167)
Defined in: [react-pacer/src/async-batcher/useAsyncBatcher.ts:168](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-batcher/useAsyncBatcher.ts#L168)

A React hook that creates an `AsyncBatcher` instance for managing asynchronous batches of items.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function useAsyncDebouncer<TFn, TSelected>(
selector): ReactAsyncDebouncer<TFn, TSelected>
```

Defined in: [react-pacer/src/async-debouncer/useAsyncDebouncer.ts:149](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-debouncer/useAsyncDebouncer.ts#L149)
Defined in: [react-pacer/src/async-debouncer/useAsyncDebouncer.ts:150](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-debouncer/useAsyncDebouncer.ts#L150)

A low-level React hook that creates an `AsyncDebouncer` instance to delay execution of an async function.

Expand Down
2 changes: 1 addition & 1 deletion docs/framework/react/reference/functions/useasyncqueuer.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function useAsyncQueuer<TValue, TSelected>(
selector): ReactAsyncQueuer<TValue, TSelected>
```

Defined in: [react-pacer/src/async-queuer/useAsyncQueuer.ts:167](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-queuer/useAsyncQueuer.ts#L167)
Defined in: [react-pacer/src/async-queuer/useAsyncQueuer.ts:168](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-queuer/useAsyncQueuer.ts#L168)

A lower-level React hook that creates an `AsyncQueuer` instance for managing an async queue of items.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function useAsyncRateLimiter<TFn, TSelected>(
selector): ReactAsyncRateLimiter<TFn, TSelected>
```

Defined in: [react-pacer/src/async-rate-limiter/useAsyncRateLimiter.ts:178](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-rate-limiter/useAsyncRateLimiter.ts#L178)
Defined in: [react-pacer/src/async-rate-limiter/useAsyncRateLimiter.ts:179](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-rate-limiter/useAsyncRateLimiter.ts#L179)

A low-level React hook that creates an `AsyncRateLimiter` instance to limit how many times an async function can execute within a time window.

Expand Down
165 changes: 165 additions & 0 deletions docs/framework/react/reference/functions/useasyncretryer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
---
id: useAsyncRetryer
title: useAsyncRetryer
---

<!-- DO NOT EDIT: this page is autogenerated from the type comments -->

# Function: useAsyncRetryer()

```ts
function useAsyncRetryer<TFn, TSelected>(
fn,
options,
selector): ReactAsyncRetryer<TFn, TSelected>
```

Defined in: [react-pacer/src/async-retryer/useAsyncRetryer.ts:152](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-retryer/useAsyncRetryer.ts#L152)

A low-level React hook that creates an `AsyncRetryer` instance to retry execution of an async function.

This hook is designed to be flexible and state-management agnostic - it simply returns a retryer instance that
you can integrate with any state management solution (useState, Redux, Zustand, Jotai, etc).

Async retrying automatically re-executes a failed async function up to a specified number of attempts with
configurable backoff strategies. This is useful for handling transient errors like network failures, temporary
server issues, or rate limiting where you want to automatically retry the operation.

Error Handling:
- If an `onError` handler is provided, it will be called for every error during execution
- If an `onLastError` handler is provided, it will be called only for the final error after all retries fail
- If `throwOnError` is 'last' (default), only the final error after all retries will be thrown
- If `throwOnError` is true, every error will be thrown immediately (disables retrying)
- If `throwOnError` is false, errors are never thrown and undefined is returned instead

## State Management and Selector

The hook uses TanStack Store for reactive state management. The `selector` parameter allows you
to specify which state changes will trigger a re-render, optimizing performance by preventing
unnecessary re-renders when irrelevant state changes occur.

**By default, there will be no reactive state subscriptions** and you must opt-in to state
tracking by providing a selector function. This prevents unnecessary re-renders and gives you
full control over when your component updates. Only when you provide a selector will the
component re-render when the selected state values change.

Available state properties:
- `currentAttempt`: The current retry attempt number (0 when not executing)
- `executionCount`: Total number of completed executions (successful or failed)
- `isExecuting`: Whether the retryer is currently executing the function
- `lastError`: The most recent error encountered during execution
- `lastExecutionTime`: Timestamp of the last execution completion in milliseconds
- `lastResult`: The result from the most recent successful execution
- `status`: Current execution status ('disabled' | 'idle' | 'executing' | 'retrying')
- `totalExecutionTime`: Total time spent executing (including retries) in milliseconds

## Type Parameters

• **TFn** *extends* `AnyAsyncFunction`

• **TSelected** = \{\}

## Parameters

### fn

`TFn`

### options

`AsyncRetryerOptions`\<`TFn`\>

### selector

(`state`) => `TSelected`

## Returns

[`ReactAsyncRetryer`](../../interfaces/reactasyncretryer.md)\<`TFn`, `TSelected`\>

## Example

```tsx
// Default behavior - no reactive state subscriptions
const apiRetryer = useAsyncRetryer(
async (userId: string) => {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) throw new Error('Failed to fetch user');
return response.json();
},
{ maxAttempts: 3, backoff: 'exponential' }
);

// Opt-in to re-render when execution state changes (optimized for loading indicators)
const apiRetryer = useAsyncRetryer(
async (userId: string) => {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) throw new Error('Failed to fetch user');
return response.json();
},
{ maxAttempts: 3, backoff: 'exponential' },
(state) => ({
isExecuting: state.isExecuting,
currentAttempt: state.currentAttempt
})
);

// Opt-in to re-render when results are available (optimized for data display)
const apiRetryer = useAsyncRetryer(
async (userId: string) => {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) throw new Error('Failed to fetch user');
return response.json();
},
{ maxAttempts: 3, backoff: 'exponential' },
(state) => ({
lastResult: state.lastResult,
executionCount: state.executionCount
})
);

// Opt-in to re-render when error state changes (optimized for error handling)
const apiRetryer = useAsyncRetryer(
async (userId: string) => {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) throw new Error('Failed to fetch user');
return response.json();
},
{
maxAttempts: 3,
backoff: 'exponential',
onError: (error) => console.error('API call failed:', error),
onLastError: (error) => console.error('All retries failed:', error)
},
(state) => ({
lastError: state.lastError,
status: state.status
})
);

// With state management
const [userData, setUserData] = useState(null);
const { execute, state } = useAsyncRetryer(
async (userId) => {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) throw new Error('Failed to fetch user');
const data = await response.json();
setUserData(data);
return data;
},
{
maxAttempts: 5,
backoff: 'exponential',
baseWait: 1000,
onRetry: (attempt, error) => {
console.log(`Retry attempt ${attempt} after error:`, error);
},
onError: (error) => {
console.error('Request failed:', error);
}
}
);

// Access the selected state (will be empty object {} unless selector provided)
const { isExecuting, currentAttempt } = state;
```
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function useAsyncThrottler<TFn, TSelected>(
selector): ReactAsyncThrottler<TFn, TSelected>
```

Defined in: [react-pacer/src/async-throttler/useAsyncThrottler.ts:160](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-throttler/useAsyncThrottler.ts#L160)
Defined in: [react-pacer/src/async-throttler/useAsyncThrottler.ts:161](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/async-throttler/useAsyncThrottler.ts#L161)

A low-level React hook that creates an `AsyncThrottler` instance to limit how often an async function can execute.

Expand Down
2 changes: 1 addition & 1 deletion docs/framework/react/reference/functions/usebatcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function useBatcher<TValue, TSelected>(
selector): ReactBatcher<TValue, TSelected>
```

Defined in: [react-pacer/src/batcher/useBatcher.ts:121](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/batcher/useBatcher.ts#L121)
Defined in: [react-pacer/src/batcher/useBatcher.ts:122](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/batcher/useBatcher.ts#L122)

A React hook that creates and manages a Batcher instance.

Expand Down
2 changes: 1 addition & 1 deletion docs/framework/react/reference/functions/usedebouncer.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function useDebouncer<TFn, TSelected>(
selector): ReactDebouncer<TFn, TSelected>
```

Defined in: [react-pacer/src/debouncer/useDebouncer.ts:102](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/debouncer/useDebouncer.ts#L102)
Defined in: [react-pacer/src/debouncer/useDebouncer.ts:103](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/debouncer/useDebouncer.ts#L103)

A React hook that creates and manages a Debouncer instance.

Expand Down
18 changes: 18 additions & 0 deletions docs/framework/react/reference/functions/usedefaultpaceroptions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
id: useDefaultPacerOptions
title: useDefaultPacerOptions
---

<!-- DO NOT EDIT: this page is autogenerated from the type comments -->

# Function: useDefaultPacerOptions()

```ts
function useDefaultPacerOptions(): PacerProviderOptions
```

Defined in: [react-pacer/src/provider/PacerProvider.tsx:62](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/provider/PacerProvider.tsx#L62)

## Returns

[`PacerProviderOptions`](../../interfaces/pacerprovideroptions.md)
18 changes: 18 additions & 0 deletions docs/framework/react/reference/functions/usepacercontext.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
id: usePacerContext
title: usePacerContext
---

<!-- DO NOT EDIT: this page is autogenerated from the type comments -->

# Function: usePacerContext()

```ts
function usePacerContext(): null | PacerContextValue
```

Defined in: [react-pacer/src/provider/PacerProvider.tsx:58](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/provider/PacerProvider.tsx#L58)

## Returns

`null` \| `PacerContextValue`
2 changes: 1 addition & 1 deletion docs/framework/react/reference/functions/usequeuer.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function useQueuer<TValue, TSelected>(
selector): ReactQueuer<TValue, TSelected>
```

Defined in: [react-pacer/src/queuer/useQueuer.ts:132](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/queuer/useQueuer.ts#L132)
Defined in: [react-pacer/src/queuer/useQueuer.ts:133](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/queuer/useQueuer.ts#L133)

A React hook that creates and manages a Queuer instance.

Expand Down
2 changes: 1 addition & 1 deletion docs/framework/react/reference/functions/useratelimiter.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function useRateLimiter<TFn, TSelected>(
selector): ReactRateLimiter<TFn, TSelected>
```

Defined in: [react-pacer/src/rate-limiter/useRateLimiter.ts:141](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/rate-limiter/useRateLimiter.ts#L141)
Defined in: [react-pacer/src/rate-limiter/useRateLimiter.ts:142](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/rate-limiter/useRateLimiter.ts#L142)

A low-level React hook that creates a `RateLimiter` instance to enforce rate limits on function execution.

Expand Down
2 changes: 1 addition & 1 deletion docs/framework/react/reference/functions/usethrottler.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function useThrottler<TFn, TSelected>(
selector): ReactThrottler<TFn, TSelected>
```

Defined in: [react-pacer/src/throttler/useThrottler.ts:107](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/throttler/useThrottler.ts#L107)
Defined in: [react-pacer/src/throttler/useThrottler.ts:108](https://github.com/TanStack/pacer/blob/main/packages/react-pacer/src/throttler/useThrottler.ts#L108)

A low-level React hook that creates a `Throttler` instance that limits how often the provided function can execute.

Expand Down
7 changes: 7 additions & 0 deletions docs/framework/react/reference/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ title: "@tanstack/react-pacer"

## Interfaces

- [PacerProviderOptions](../interfaces/pacerprovideroptions.md)
- [PacerProviderProps](../interfaces/pacerproviderprops.md)
- [ReactAsyncBatcher](../interfaces/reactasyncbatcher.md)
- [ReactAsyncDebouncer](../interfaces/reactasyncdebouncer.md)
- [ReactAsyncQueuer](../interfaces/reactasyncqueuer.md)
- [ReactAsyncRateLimiter](../interfaces/reactasyncratelimiter.md)
- [ReactAsyncRetryer](../interfaces/reactasyncretryer.md)
- [ReactAsyncThrottler](../interfaces/reactasyncthrottler.md)
- [ReactBatcher](../interfaces/reactbatcher.md)
- [ReactDebouncer](../interfaces/reactdebouncer.md)
Expand All @@ -22,6 +25,7 @@ title: "@tanstack/react-pacer"

## Functions

- [PacerProvider](../functions/pacerprovider.md)
- [useAsyncBatchedCallback](../functions/useasyncbatchedcallback.md)
- [useAsyncBatcher](../functions/useasyncbatcher.md)
- [useAsyncDebouncedCallback](../functions/useasyncdebouncedcallback.md)
Expand All @@ -30,6 +34,7 @@ title: "@tanstack/react-pacer"
- [useAsyncQueuer](../functions/useasyncqueuer.md)
- [useAsyncRateLimitedCallback](../functions/useasyncratelimitedcallback.md)
- [useAsyncRateLimiter](../functions/useasyncratelimiter.md)
- [useAsyncRetryer](../functions/useasyncretryer.md)
- [useAsyncThrottledCallback](../functions/useasyncthrottledcallback.md)
- [useAsyncThrottler](../functions/useasyncthrottler.md)
- [useBatchedCallback](../functions/usebatchedcallback.md)
Expand All @@ -38,6 +43,8 @@ title: "@tanstack/react-pacer"
- [useDebouncedState](../functions/usedebouncedstate.md)
- [useDebouncedValue](../functions/usedebouncedvalue.md)
- [useDebouncer](../functions/usedebouncer.md)
- [useDefaultPacerOptions](../functions/usedefaultpaceroptions.md)
- [usePacerContext](../functions/usepacercontext.md)
- [useQueuedState](../functions/usequeuedstate.md)
- [useQueuedValue](../functions/usequeuedvalue.md)
- [useQueuer](../functions/usequeuer.md)
Expand Down
Loading
Loading