vega-frontend-monorepo/apps/trading/hooks/react-singleton-hook/singletonHook.js

52 lines
1.3 KiB
JavaScript
Raw Normal View History

import { useEffect, useState } from 'react';
import { addHook } from './components/SingletonHooksContainer';
import { batch } from './utils/env';
export const singletonHook = (initValue, useHookBody, unmount = false) => {
let mounted = false;
let removeHook = undefined
let initStateCalculated = false;
let lastKnownState = undefined;
let consumers = [];
const applyStateChange = (newState) => {
lastKnownState = newState;
batch(() => consumers.forEach(c => c(newState)));
};
const stateInitializer = () => {
if (!initStateCalculated) {
lastKnownState = typeof initValue === 'function' ? initValue() : initValue;
initStateCalculated = true;
}
return lastKnownState;
};
return () => {
const [state, setState] = useState(stateInitializer);
useEffect(() => {
if (!mounted) {
mounted = true;
removeHook = addHook({ initValue, useHookBody, applyStateChange });
}
consumers.push(setState);
if (lastKnownState !== state) {
setState(lastKnownState);
}
return () => {
consumers.splice(consumers.indexOf(setState), 1);
if (consumers.length === 0 && unmount) {
removeHook();
mounted = false;
}
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return state;
};
};