본문으로 건너뛰기

함수: useRateLimitedValue()

function useRateLimitedValue<TValue, TSelected>(
value,
options,
selector?): [TValue, ReactRateLimiter<Dispatch<SetStateAction<TValue>>, TSelected>];

정의 위치: react-pacer/src/rate-limiter/useRateLimitedValue.ts:96

시간 윈도우 안에서 일정 횟수 이하로 업데이트되는 요청률 제한 값 버전을 생성하는 상위 수준 React 훅입니다. 이 훅은 내부적으로 React의 useState를 사용해 요청률이 제한된 상태를 관리합니다.

요청률 제한은 단순한 "하드 제한" 방식입니다. 한도에 도달할 때까지 모든 업데이트를 허용한 뒤 윈도우가 초기화될 때까지 이후 업데이트를 차단합니다. 스로틀이나 디바운스와 달리 업데이트 간격을 조정하거나 지능적으로 합치지 않습니다. 따라서 빠른 업데이트가 몰린 뒤 업데이트가 없는 기간이 이어질 수 있습니다.

요청률 제한기는 두 가지 윈도우 유형을 지원합니다.

  • 'fixed': 윈도우 기간이 지나면 초기화되는 엄격한 윈도우입니다. 윈도우 안의 모든 업데이트가 한도에 포함되며 기간이 지나면 윈도우가 완전히 초기화됩니다.
  • 'sliding': 이전 업데이트가 만료됨에 따라 업데이트를 허용하는 롤링 윈도우입니다. 시간에 걸쳐 더 일정한 업데이트율을 제공합니다.

더 부드러운 업데이트 패턴이 필요하다면 다음을 고려합니다.

  • useThrottledValue: 업데이트 간격을 일정하게 유지하려는 경우(예: UI 변경)
  • useDebouncedValue: 빠른 업데이트를 단일 업데이트로 합치려는 경우(예: 검색 입력)

요청률 제한은 API 요청률 제한처럼 엄격한 제한을 적용해야 할 때 주로 사용해야 합니다.

훅은 다음 요소를 담은 튜플을 반환합니다.

  • 구성된 요청률 제한에 따라 업데이트되는 요청률 제한 값
  • 제어 메서드를 제공하는 요청률 제한기 인스턴스

React 상태 관리 없이 요청률 제한 동작을 더 직접 제어하려면 하위 수준 useRateLimiter 훅을 대신 사용합니다.

상태 관리와 셀렉터​

훅은 내부 요청률 제한기 인스턴스를 통해 반응형 상태 관리에 TanStack Store를 사용합니다. selector 매개변수를 사용하면 요청률 제한기 상태의 어떤 변경이 재렌더링을 트리거할지 지정할 수 있으며, 관련 없는 상태가 변경될 때 불필요한 재렌더링을 방지하여 성능을 최적화합니다.

기본적으로 반응형 상태 구독은 없습니다. 상태 추적을 명시적으로 활성화하려면 셀렉터 함수를 제공해야 합니다. 이렇게 하면 불필요한 재렌더링을 방지하고 컴포넌트 업데이트 시점을 완전히 제어할 수 있습니다. 셀렉터를 제공한 경우에만 선택한 상태 값이 변경될 때 컴포넌트가 다시 렌더링됩니다.

사용 가능한 요청률 제한기 상태 속성:

  • executionCount: 완료된 함수 실행 횟수
  • executionTimes: 요청률 제한 계산을 위해 실행이 발생한 시점의 타임스탬프 배열
  • rejectionCount: 요청률 제한으로 거부된 함수 실행 횟수

타입 매개변수​

TValue​

TValue

TSelected​

TSelected = RateLimiterState

매개변수​

value​

TValue

options​

ReactRateLimiterOptions&lt;Dispatch&lt;SetStateAction&lt;TValue>>, TSelected>

selector?​

(state) => TSelected

반환값​

[TValue, ReactRateLimiter&lt;Dispatch&lt;SetStateAction&lt;TValue>>, TSelected>]

예시​

// Default behavior - no reactive state subscriptions
const [rateLimitedValue, rateLimiter] = useRateLimitedValue(rawValue, {
limit: 5,
window: 60000,
windowType: 'sliding'
});

// Opt-in to re-render when execution count changes (optimized for tracking successful updates)
const [rateLimitedValue, rateLimiter] = useRateLimitedValue(
rawValue,
{ limit: 5, window: 60000, windowType: 'sliding' },
(state) => ({ executionCount: state.executionCount })
);

// Opt-in to re-render when rejection count changes (optimized for tracking rate limit violations)
const [rateLimitedValue, rateLimiter] = useRateLimitedValue(
rawValue,
{ limit: 5, window: 60000, windowType: 'sliding' },
(state) => ({ rejectionCount: state.rejectionCount })
);

// Opt-in to re-render when execution times change (optimized for window calculations)
const [rateLimitedValue, rateLimiter] = useRateLimitedValue(
rawValue,
{ limit: 5, window: 60000, windowType: 'sliding' },
(state) => ({ executionTimes: state.executionTimes })
);

// With rejection callback and fixed window
const [rateLimitedValue, rateLimiter] = useRateLimitedValue(rawValue, {
limit: 3,
window: 5000,
windowType: 'fixed',
onReject: (rateLimiter) => {
console.log(`Update rejected. Try again in ${rateLimiter.getMsUntilNextWindow()}ms`);
}
});

// Access the selected rate limiter state (will be empty object {} unless selector provided)
const { executionCount, rejectionCount } = rateLimiter.state;