UNPKG

@react-hookz/web

Version:

React hooks done right, for browser and SSR.

69 lines (68 loc) 2.96 kB
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; /* eslint-disable @typescript-eslint/no-explicit-any */ import { useEffect, useMemo } from 'react'; import { useIsMounted, useSyncedRef } from '..'; import { hasOwnProperty } from "../util/misc.js"; /** * Subscribes an event listener to the target, and automatically unsubscribes * it on unmount. * * @param target Element ref object or element itself. * @param params Parameters specific for target's `addEventListener`. Commonly, * it is `[eventName, listener, options]`. */ export function useEventListener(target) { var params = []; for (var _i = 1; _i < arguments.length; _i++) { params[_i - 1] = arguments[_i]; } var isMounted = useIsMounted(); // create static event listener var listenerRef = useSyncedRef(params[1]); var eventListener = useMemo(function () { // as some event listeners designed to be used through `this` // it is better to make listener a conventional function as it // infers call context // eslint-disable-next-line func-names return function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } // normally, such situation should not happen, but better to // have back covered /* istanbul ignore next */ if (!isMounted()) return; // we dont care if non-listener provided, simply dont do anything /* istanbul ignore else */ if (typeof listenerRef.current === 'function') { listenerRef.current.apply(this, args); } else if (typeof listenerRef.current.handleEvent === 'function') { listenerRef.current.handleEvent.apply(this, args); } }; }, // eslint-disable-next-line react-hooks/exhaustive-deps []); useEffect(function () { var tgt = target && hasOwnProperty(target, 'current') ? target.current : target; if (!tgt) return; var restParams = params.slice(2); // eslint-disable-next-line @typescript-eslint/no-unsafe-argument tgt.addEventListener.apply(tgt, __spreadArray([params[0], eventListener], restParams, false)); // eslint-disable-next-line @typescript-eslint/no-unsafe-argument return function () { return tgt.removeEventListener.apply(tgt, __spreadArray([params[0], eventListener], restParams, false)); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [target, params[0]]); }