Created
March 24, 2022 12:07
-
-
Save kossnocorp/c8ee8b2e7e078850dd4c2b9ce9038123 to your computer and use it in GitHub Desktop.
Preact event/dispatch hook
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect } from 'preact/hooks' | |
/** | |
* Generates an event hook / dispatch function pair for the given payload. | |
* | |
* @returns the hook and dispatch functions | |
*/ | |
export function createEventHooks<Payload>() { | |
const { useEvent, dispatchEvent } = createEventsHooks() | |
const event = Date.now().toString() | |
return { | |
useEvent: (callback: (payload: Payload) => void) => | |
useEvent(event, callback), | |
dispatchEvent: (payload: Payload) => dispatchEvent(event, payload), | |
} | |
} | |
/** | |
* Generates an event hook / dispatch function pair for the given events map. | |
* | |
* @returns the hook and dispatch functions | |
*/ | |
export function createEventsHooks<EventMap extends Record<string, unknown>>() { | |
const element = document.createElement('div') | |
/** | |
* Listens for the given event and calls the callback with the event payload. | |
* | |
* @param event - the event name to listen to | |
* @param callback - the callback to call when the event is dispatched | |
*/ | |
function useEvent< | |
EventName extends keyof EventMap, | |
Payload extends EventMap[EventName] | |
>(event: EventName, callback: (payload: Payload) => void) { | |
useEffect(() => { | |
const listener = ((event: CustomEvent<Payload>) => | |
callback(event.detail)) as EventListener // TS doesn't like custom events: https://github.com/microsoft/TypeScript/issues/28357 | |
element.addEventListener(event.toString(), listener) | |
return () => element.removeEventListener(event.toString(), listener) | |
}, [event]) | |
} | |
/** | |
* Dispatches the given event with the given payload. | |
* | |
* @param event - the event name to dispatch | |
* @param payload - the payload to dispatch | |
*/ | |
function dispatchEvent<EventName extends keyof EventMap>( | |
event: EventName, | |
...[payload]: EventMap[EventName] extends undefined | |
? [] | |
: [EventMap[EventName]] | |
) { | |
element.dispatchEvent( | |
new CustomEvent(event.toString(), { detail: payload }) | |
) | |
} | |
return { useEvent, dispatchEvent } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment