UNPKG

react-singleton-hook

Version:
60 lines (59 loc) 1.86 kB
import { useEffect, useState } from 'react'; import { addHook } from './components/SingletonHooksContainer'; import { batch } from './utils/env'; export var singletonHook = function singletonHook(initValue, useHookBody, options) { if (options === void 0) { options = {}; } var mounted = false; var removeHook = undefined; var initStateCalculated = false; var lastKnownState = undefined; var consumers = []; var _options = options, _options$unmountIfNoC = _options.unmountIfNoConsumers, unmountIfNoConsumers = _options$unmountIfNoC === void 0 ? false : _options$unmountIfNoC; var applyStateChange = function applyStateChange(newState) { lastKnownState = newState; batch(function () { return consumers.forEach(function (c) { return c(newState); }); }); }; var stateInitializer = function stateInitializer() { if (!initStateCalculated) { lastKnownState = typeof initValue === 'function' ? initValue() : initValue; initStateCalculated = true; } return lastKnownState; }; return function () { var _useState = useState(stateInitializer), state = _useState[0], setState = _useState[1]; useEffect(function () { if (!mounted) { mounted = true; removeHook = addHook({ initValue: initValue, useHookBody: useHookBody, applyStateChange: applyStateChange }); } consumers.push(setState); if (lastKnownState !== state) { setState(lastKnownState); } return function () { consumers.splice(consumers.indexOf(setState), 1); if (consumers.length === 0 && unmountIfNoConsumers) { removeHook(); mounted = false; } }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return state; }; };