본문으로 건너뛰기

함수: useRateLimitedState()

function useRateLimitedState<TValue, TSelected>(
value,
options,
selector?): [TValue, Dispatch<StateUpdater<TValue>>, PreactRateLimiter<Dispatch<StateUpdater<TValue>>, TSelected>];

정의 위치: preact-pacer/src/rate-limiter/useRateLimitedState.ts:108

시간 윈도우 안의 상태 업데이트에 하드 제한을 적용하는 요청률 제한 상태 값을 생성하는 Preact 훅입니다. Preact의 useState와 요청률 제한 기능을 결합해 제어된 상태 업데이트를 제공합니다.

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

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

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

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

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

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

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

  • 요청률이 제한된 상태 값
  • 구성된 제한을 준수하는 요청률 제한 setter 함수
  • 추가 제어를 위한 rateLimiter 인스턴스

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

상태 관리와 셀렉터

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

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

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

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

타입 매개변수

TValue

TValue

TSelected

TSelected = RateLimiterState

매개변수

value

TValue

options

PreactRateLimiterOptions&lt;Dispatch&lt;StateUpdater&lt;TValue>>, TSelected>

selector?

(state) => TSelected

반환값

[TValue, Dispatch&lt;StateUpdater&lt;TValue>>, PreactRateLimiter&lt;Dispatch&lt;StateUpdater&lt;TValue>>, TSelected>]

예시

// Default behavior - no reactive state subscriptions
const [value, setValue, rateLimiter] = useRateLimitedState(0, {
limit: 5,
window: 60000,
windowType: 'sliding'
});

// Opt-in to re-render when execution count changes (optimized for tracking successful updates)
const [value, setValue, rateLimiter] = useRateLimitedState(
0,
{ 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 [value, setValue, rateLimiter] = useRateLimitedState(
0,
{ limit: 5, window: 60000, windowType: 'sliding' },
(state) => ({ rejectionCount: state.rejectionCount })
);

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

// With rejection callback and fixed window
const [value, setValue] = useRateLimitedState(0, {
limit: 3,
window: 5000,
windowType: 'fixed',
onReject: (rateLimiter) => {
alert(`Rate limit reached. Try again in ${rateLimiter.getMsUntilNextWindow()}ms`);
}
});

// Access rateLimiter methods if needed
const handleSubmit = () => {
const remaining = rateLimiter.getRemainingInWindow();
if (remaining > 0) {
setValue(newValue);
} else {
showRateLimitWarning();
}
};

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