import { MutableRefObject, useEffect, useRef } from "react"; import { eventNameFactory } from "../utils/eventNameFactory"; function addEventListener<T extends EventTarget, E extends Event>( element: T, type: string, handler: (this: T, evt: E) => void ) { element.addEventListener(type, handler as (evt: Event) => void); } /** * A hook to receive data from the client in the following schema: * * { * "app": "app-name", * "method": "method-name", * "data": { anyValue: 1 } * } * * @param app {string} The app name which the client will emit to * @param method {string} The specific `method` field that should be listened for. * @param handler {function} The callback function that will handle data received from the client * @returns {void} void * @example * const [dataState, setDataState] = useState<boolean>(); * useNuiEvent<boolean>("appname", "methodname", setDataState); **/ export const useNuiEvent = <D = unknown>(app: string, method: string, handler: (r: D) => void): void => { const savedHandler: MutableRefObject<(r: D) => void> = useRef(); // When handler value changes set mutable ref to handler val useEffect(() => { savedHandler.current = handler; }, [handler]); useEffect(() => { const eventName = eventNameFactory(app, method); const eventListener = (event) => { if (savedHandler.current && savedHandler.current.call) { const { data } = event; const newData = data; savedHandler.current(newData as D); } }; addEventListener(window, eventName, eventListener); // Remove Event Listener on component cleanup return () => window.removeEventListener(eventName, eventListener); }, [app, method]); };