Skip to content

Instantly share code, notes, and snippets.

@kossnocorp
Created March 24, 2022 12:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kossnocorp/c8ee8b2e7e078850dd4c2b9ce9038123 to your computer and use it in GitHub Desktop.
Save kossnocorp/c8ee8b2e7e078850dd4c2b9ce9038123 to your computer and use it in GitHub Desktop.
Preact event/dispatch hook
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