@react-hookz/web
Version:
React hooks done right, for browser and SSR.
69 lines (68 loc) • 2.96 kB
JavaScript
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]]);
}