react-use-event-hook
Version:
Same as React's `useCallback`, but returns a stable reference.
47 lines • 2.01 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.useEvent = void 0;
const react_1 = __importDefault(require("react"));
/**
* Suppress the warning when using useLayoutEffect with SSR. (https://reactjs.org/link/uselayouteffect-ssr)
* Make use of useInsertionEffect if available.
*/
const useInsertionEffect = typeof window !== "undefined"
? // useInsertionEffect is available in React 18+
react_1.default.useInsertionEffect || react_1.default.useLayoutEffect
: () => { };
/**
* Similar to useCallback, with a few subtle differences:
* - The returned function is a stable reference, and will always be the same between renders
* - No dependency lists required
* - Properties or state accessed within the callback will always be "current"
*/
function useEvent(callback) {
// Keep track of the latest callback:
const latestRef = react_1.default.useRef(useEvent_shouldNotBeInvokedBeforeMount);
useInsertionEffect(() => {
latestRef.current = callback;
}, [callback]);
// Create a stable callback that always calls the latest callback:
// using useRef instead of useCallback avoids creating and empty array on every render
const stableRef = react_1.default.useRef(null);
if (!stableRef.current) {
stableRef.current = function () {
return latestRef.current.apply(this, arguments);
};
}
return stableRef.current;
}
exports.useEvent = useEvent;
/**
* Render methods should be pure, especially when concurrency is used,
* so we will throw this error if the callback is called while rendering.
*/
function useEvent_shouldNotBeInvokedBeforeMount() {
throw new Error("INVALID_USEEVENT_INVOCATION: the callback from useEvent cannot be invoked before the component has mounted.");
}
exports.default = useEvent;
//# sourceMappingURL=useEvent.js.map