본문으로 건너뛰기

함수: useDebouncer()

function useDebouncer<TFn, TSelected>(
fn,
options,
selector): PreactDebouncer<TFn, TSelected>;

정의 위치: preact-pacer/src/debouncer/useDebouncer.ts:163

Debouncer 인스턴스를 생성하고 관리하는 Preact 훅입니다.

내장 상태 관리 없이 Debouncer의 기능에 직접 접근할 수 있는 하위 수준 훅입니다. 따라서 선호하는 어떤 상태 관리 솔루션 (useState, Redux, Zustand 등)과도 통합할 수 있습니다.

이 훅은 함수 호출 빈도를 제한하는 디바운스 기능을 제공하며, 지정된 지연 시간 동안 기다린 뒤 최신 호출을 실행합니다. 창 크기 조정, 스크롤 이벤트 또는 실시간 검색 입력처럼 빈번한 이벤트를 처리할 때 유용합니다.

디바운서는 마지막 호출 후 지정된 대기 시간이 경과해야 함수를 실행합니다. 대기 시간이 끝나기 전에 함수가 다시 호출되면 타이머가 초기화되고 다시 대기하기 시작합니다.

상태 관리와 셀렉터

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

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

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

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

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

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

사용 가능한 상태 속성:

  • canLeadingExecute: 디바운서가 선행 에지에서 실행될 수 있는지 여부
  • executionCount: 완료된 함수 실행 횟수
  • isPending: 디바운서가 실행을 트리거할 타임아웃을 기다리는지 여부
  • lastArgs: 가장 최근 maybeExecute 호출의 인수
  • status: 현재 실행 상태('disabled' | 'idle' | 'pending')

언마운트 동작

기본적으로 컴포넌트가 언마운트되면 훅은 대기 중인 실행을 취소합니다. 이를 사용자 지정하려면 onUnmount 옵션을 사용합니다. 예를 들어 대기 중인 작업을 대신 플러시하려면 다음과 같이 합니다.

const debouncer = useDebouncer(fn, {
wait: 500,
onUnmount: (d) => d.flush()
});

타입 매개변수

TFn

TFn extends AnyFunction

TSelected

TSelected = { }

매개변수

fn

TFn

options

PreactDebouncerOptions&lt;TFn, TSelected>

selector

(state) => TSelected

반환값

PreactDebouncer&lt;TFn, TSelected>

예시

// Default behavior - no reactive state subscriptions
const searchDebouncer = useDebouncer(
(query: string) => fetchSearchResults(query),
{ wait: 500 }
);

// Subscribe to state changes deep in component tree using Subscribe HOC
<searchDebouncer.Subscribe selector={(state) => ({ isPending: state.isPending })}>
{({ isPending }) => (
<div>{isPending ? 'Searching...' : 'Ready'}</div>
)}
</searchDebouncer.Subscribe>

// Opt-in to re-render when isPending changes at hook level (optimized for loading states)
const searchDebouncer = useDebouncer(
(query: string) => fetchSearchResults(query),
{ wait: 500 },
(state) => ({ isPending: state.isPending })
);

// Opt-in to re-render when executionCount changes (optimized for tracking execution)
const searchDebouncer = useDebouncer(
(query: string) => fetchSearchResults(query),
{ wait: 500 },
(state) => ({ executionCount: state.executionCount })
);

// Multiple state properties - re-render when any of these change
const searchDebouncer = useDebouncer(
(query: string) => fetchSearchResults(query),
{ wait: 500 },
(state) => ({
isPending: state.isPending,
executionCount: state.executionCount,
status: state.status
})
);

// In an event handler
const handleChange = (e) => {
searchDebouncer.maybeExecute(e.target.value);
};

// Access the selected state (will be empty object {} unless selector provided)
const { isPending } = searchDebouncer.state;