EventExtender
자식 컴포넌트의 이벤트 핸들러를 확장하여 전후 처리
를 가능하게 하는 컴포넌트입니다.
shouldAwait
옵션에 따라 다음과 같이 동작합니다:
shouldAwait: false
(기본값)
- 비동기 함수를 await 하지 않습니다.
beforeEvent → 원본 이벤트 → afterEvent
순서로 실행되지만, 각 단계의 완료를 기다리지 않습니다.- 일반적인 이벤트 호출 순서를 유지합니다.
- 예시:
mouseDown -> mouseUp -> click
호출 순서가 유지됩니다.
- 예시:
shouldAwait: true
- 비동기 함수를 await 합니다.
beforeEvent → 원본 이벤트 → afterEvent
순서로 실행을 보장하며, 각 단계의 완료를 기다립니다.- 주의: 일반적인 이벤트 호출 순서와 달라질 수 있습니다.
- 예시:
mouseUp
이벤트는click
이벤트 이전에 호출되는게 일반적이지만,onMouseUp
이벤트를 캡처하면mouseUp
이벤트가click
이벤트 이후에 호출됩니다.
- 예시:
Code
Interface
typescript
/**
* @description HTML 요소들의 태그 이름 타입 (예: "div", "span", "input" 등)
*/
type HTMLElementType = keyof JSX.IntrinsicElements;
/**
* @description React.DOMAttributes<HTMLElement>에 정의된 이벤트
* - "on"으로 시작하는 이벤트 핸들러 이름만 포함 (예: "onClick", "onChange", "onSubmit" 등)
*/
type EventNames = keyof React.DOMAttributes<HTMLElement> & `on${string}`;
/**
* @description 특정 HTML 요소의 특정 이벤트에 대한 이벤트 객체 타입을 추론하는 제네릭 타입
* @template K - HTML 요소 타입 (예: "button", "input" 등)
* @template E - 이벤트 핸들러 이름 (예: "onClick", "onChange" 등)
* @returns 해당 이벤트의 이벤트 객체 타입 또는 never
*/
type ElementEventType<
K extends HTMLElementType,
E extends EventNames
> = JSX.IntrinsicElements[K][E] extends ((e: infer Event) => void) | undefined
? Event
: never;
typescript
interface EventExtenderProps<K extends HTMLElementType, E extends EventNames> {
children: JSX.Element;
capture: E;
shouldAwait?: boolean; // 기본값: false
beforeEvent?: (e: ElementEventType<K, E>) => void | Promise<void>;
afterEvent?: (e: ElementEventType<K, E>) => void | Promise<void>;
}
const EventExtender: <
K extends keyof JSX.IntrinsicElements,
E extends EventNames
>({
children,
capture,
shouldAwait,
beforeEvent,
afterEvent,
}: EventExtenderProps<K, E>) => JSX.Element;
Usage
기본 사용법
typescript
import { EventExtender } from '@modern-kit/react'
const Example = () => {
return (
<EventExtender
capture="onClick"
beforeEvent={(e: React.MouseEvent<HTMLButtonElement>) => {
console.log('클릭 전', e);
}}
afterEvent={(e: React.MouseEvent<HTMLButtonElement>) => {
console.log('클릭 후', e);
}}>
<button onClick={(e) => console.log('클릭', e)}>Sync Button</button>
</EventExtender>
);
};
개발자 도구 콘솔에서 확인해주세요.
비동기 이벤트 처리
typescript
import { EventExtender } from '@modern-kit/react'
const Example = () => {
return (
<EventExtender
shouldAwait={true} // (*)
capture="onClick"
beforeEvent={async (e: React.MouseEvent<HTMLButtonElement>) => {
await delay(500);
console.log('클릭 전', e);
}}
afterEvent={async (e: React.MouseEvent<HTMLButtonElement>) => {
await delay(500);
console.log('클릭 후', e);
}}>
<button
onClick={async (e: React.MouseEvent<HTMLButtonElement>) => {
await delay(500);
console.log('클릭', e);
}}>
Async Button
</button>
</EventExtender>
);
};
개발자 도구 콘솔에서 확인해주세요.