본문으로 건너뛰기

함수: useAsyncBatcher()

function useAsyncBatcher<TValue, TSelected>(
fn,
options,
selector): ReactAsyncBatcher<TValue, TSelected>;

정의 위치: react-pacer/src/async-batcher/useAsyncBatcher.ts:235

항목의 비동기 배치를 관리하는 AsyncBatcher 인스턴스를 생성하는 React 훅입니다.

useBatcher 훅의 비동기 버전입니다. 동기 버전과 달리 이 비동기 배처는 다음을 지원합니다.

  • 프로미스를 처리하고 배치 실행 결과를 반환합니다.
  • 구성 가능한 오류 동작으로 오류를 처리합니다.
  • 성공, 오류 및 완료 횟수를 별도로 추적합니다.
  • 배치 실행 여부를 상태로 추적합니다.
  • 배치 함수 실행 결과를 반환합니다.

기능:

  • 구성 가능한 배치 크기 및 대기 시간
  • getShouldExecute를 통한 사용자 지정 배치 처리 로직
  • 배치 작업 모니터링을 위한 이벤트 콜백
  • 실패한 배치 작업의 오류 처리
  • 자동 또는 수동 배치 처리

배처는 다음 조건에 따라 항목을 모아 배치로 처리합니다.

  • 최대 배치 크기(배치당 항목 수)
  • 시간 기반 배칭(X밀리초 후 처리)
  • getShouldExecute를 통한 사용자 지정 배치 처리 로직

오류 처리:

  • onError 핸들러를 제공하면 오류 및 배처 인스턴스와 함께 호출됩니다.
  • throwOnError가 true이면(onError 핸들러가 없을 때의 기본값) 오류가 발생합니다.
  • throwOnError가 false이면(onError 핸들러가 있을 때의 기본값) 오류가 처리된 것으로 간주됩니다.
  • onError와 throwOnError를 함께 사용할 수 있으며, 오류가 발생하기 전에 핸들러가 호출됩니다.
  • 내부 AsyncBatcher 인스턴스를 사용해 오류 상태를 확인할 수 있습니다.

상태 관리와 셀렉터

훅은 반응형 상태 관리에 TanStack Store를 사용합니다. 다음 두 가지 방식으로 상태 변경을 구독할 수 있습니다.

1. batcher.Subscribe HOC 사용(컴포넌트 트리 구독에 권장)

Subscribe HOC를 사용하면 컴포넌트 트리 깊은 곳의 상태 변경을 구독할 때 훅에 셀렉터를 전달할 필요가 없습니다. 자식 컴포넌트에서 상태를 구독하려는 경우에 적합합니다.

2. selector 매개변수 사용(훅 수준 구독)

selector 매개변수를 사용하면 어떤 상태 변경이 재렌더링을 트리거할지 지정할 수 있으며 관련 없는 상태가 변경될 때 불필요한 재렌더링을 방지하여 훅 수준의 성능을 최적화합니다.

기본적으로 반응형 상태 구독은 없습니다. 상태 추적을 명시적으로 활성화하려면 셀렉터 함수를 제공하거나 Subscribe HOC를 사용해야 합니다. 이렇게 하면 불필요한 재렌더링을 방지하고 컴포넌트가 업데이트되는 시점을 완전히 제어할 수 있습니다.

사용 가능한 상태 속성:

  • errorCount: 오류가 발생한 배치 실행 횟수
  • failedItems: 배치 처리 중 실패한 항목 배열
  • isEmpty: 배처에 처리할 항목이 없는지 여부
  • isExecuting: 배치가 현재 비동기로 처리 중인지 여부
  • isPending: 배처가 배치 처리를 트리거할 타임아웃을 기다리는지 여부
  • isRunning: 배처가 활성 상태이며 항목을 자동으로 처리할지 여부
  • items: 현재 배치 처리 대기 중인 항목 배열
  • lastResult: 가장 최근 배치 실행 결과
  • settleCount: 성공 또는 오류로 완료된 배치 실행 횟수
  • size: 현재 배치 큐에 있는 항목 수
  • status: 현재 처리 상태('idle' | 'pending' | 'executing' | 'populated')
  • successCount: 성공적으로 완료된 배치 실행 횟수
  • totalItemsProcessed: 모든 배치에서 처리된 전체 항목 수
  • totalItemsFailed: 처리에 실패한 전체 항목 수

언마운트 동작

기본적으로 컴포넌트가 언마운트되면 훅은 대기 중인 배치를 취소하고 진행 중인 실행을 중단합니다. getAbortSignal()의 중단 신호를 내부 작업(예: fetch)에 전달한 경우에만 Abort가 해당 작업을 취소합니다. 이를 사용자 지정하려면 onUnmount 옵션을 사용합니다. 예를 들어 대기 중인 작업을 대신 플러시하려면 다음과 같이 합니다.

const batcher = useAsyncBatcher(fn, {
maxSize: 10,
wait: 2000,
onUnmount: (b) => b.flush()
});

참고: 비동기 유틸리티에서 flush()는 Promise를 반환하며 정리 과정에서는 실행 후 결과를 기다리지 않습니다. 배치 함수가 React 상태를 업데이트하면 해당 업데이트가 컴포넌트가 언마운트된 뒤 실행될 수 있으며, 이 경우 "setState on unmounted component" 경고가 발생할 수 있습니다. 콜백을 onUnmount에서 flush와 함께 사용할 때 적절히 보호해야 합니다.

타입 매개변수

TValue

TValue

TSelected

TSelected = { }

매개변수

fn

(items) => Promise&lt;any>

options

ReactAsyncBatcherOptions&lt;TValue, TSelected> = {}

selector

(state) => TSelected

반환값

ReactAsyncBatcher&lt;TValue, TSelected>

예시

// Basic async batcher for API requests - no reactive state subscriptions
const asyncBatcher = useAsyncBatcher(
async (items) => {
const results = await Promise.all(items.map(item => processItem(item)));
return results;
},
{ maxSize: 10, wait: 2000 }
);

// Subscribe to state changes deep in component tree using Subscribe HOC
<asyncBatcher.Subscribe selector={(state) => ({ size: state.size, isExecuting: state.isExecuting })}>
{({ size, isExecuting }) => (
<div>Batch: {size} items, {isExecuting ? 'Processing' : 'Ready'}</div>
)}
</asyncBatcher.Subscribe>

// Opt-in to re-render when execution state changes at hook level (optimized for loading indicators)
const asyncBatcher = useAsyncBatcher(
async (items) => {
const results = await Promise.all(items.map(item => processItem(item)));
return results;
},
{ maxSize: 10, wait: 2000 },
(state) => ({
isExecuting: state.isExecuting,
isPending: state.isPending,
status: state.status
})
);

// Opt-in to re-render when results are available (optimized for data display)
const asyncBatcher = useAsyncBatcher(
async (items) => {
const results = await Promise.all(items.map(item => processItem(item)));
return results;
},
{ maxSize: 10, wait: 2000 },
(state) => ({
lastResult: state.lastResult,
successCount: state.successCount,
totalItemsProcessed: state.totalItemsProcessed
})
);

// Opt-in to re-render when error state changes (optimized for error handling)
const asyncBatcher = useAsyncBatcher(
async (items) => {
const results = await Promise.all(items.map(item => processItem(item)));
return results;
},
{
maxSize: 10,
wait: 2000,
onError: (error) => console.error('Batch processing failed:', error)
},
(state) => ({
errorCount: state.errorCount,
failedItems: state.failedItems,
totalItemsFailed: state.totalItemsFailed
})
);

// Complete example with all callbacks
const asyncBatcher = useAsyncBatcher(
async (items) => {
const results = await Promise.all(items.map(item => processItem(item)));
return results;
},
{
maxSize: 10,
wait: 2000,
onSuccess: (result) => {
console.log('Batch processed successfully:', result);
},
onError: (error) => {
console.error('Batch processing failed:', error);
}
}
);

// Add items to batch
asyncBatcher.addItem(newItem);

// Manually execute batch
const result = await asyncBatcher.execute();

// Access the selected state (will be empty object {} unless selector provided)
const { isExecuting, lastResult, size } = asyncBatcher.state;