UNPKG

use-initializer

Version:

A React hook for once-only initialization with dependency tracking and cleanup

51 lines (50 loc) 1.69 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useInitializer = useInitializer; const react_1 = require("react"); /** * useMemo & useState are not suitable for once-only initialization * reinitialized on dependency change * https://github.com/facebook/react/issues/27735#issuecomment-1885624506 */ function useInitializer(initialize, dispose, deps = []) { const depsRef = (0, react_1.useRef)([]); const dependenciesChanged = !areDependenciesEqual(depsRef.current, deps); depsRef.current = deps; const ref = (0, react_1.useRef)(null); if (ref.current === null || dependenciesChanged) { // dispose any previous instance if (ref.current !== null) { dispose?.(ref.current); } ref.current = initialize(deps); } // dispose on unmount (0, react_1.useEffect)(() => { return () => { if (ref.current !== null) { dispose?.(ref.current); ref.current = null; } }; }, []); return ref.current; } /** * Compares two dependency arrays using Object.is, just like React does internally */ function areDependenciesEqual(prevDeps, nextDeps) { // First, check if both are arrays and have the same length if (!Array.isArray(prevDeps) || !Array.isArray(nextDeps) || prevDeps.length !== nextDeps.length) { return false; } // Check each dependency using Object.is for (let i = 0; i < prevDeps.length; i++) { if (!Object.is(prevDeps[i], nextDeps[i])) { return false; // Found a difference } } return true; // All dependencies are the same }