@lesnoypudge/utils-react
Version:
lesnoypudge's utils-react
57 lines (56 loc) • 1.76 kB
JavaScript
import { useConst } from "../useConst/useConst.js";
import { invariant, noop } from "@lesnoypudge/utils";
import { useRef } from "react";
const useRefManager = (initialValue) => {
const isInEffectRef = useRef(false);
const effectCallbackToCleanup = useConst(() => {
return /* @__PURE__ */ new Map();
});
const manager = useConst(() => {
const throwIfRefChanged = (callback) => {
isInEffectRef.current = true;
callback();
isInEffectRef.current = false;
};
const rawManager = {
current: initialValue,
effect: (callback) => {
throwIfRefChanged(() => {
effectCallbackToCleanup.set(callback, callback(rawManager.current) ?? noop);
});
return () => {
throwIfRefChanged(() => {
var _a;
(_a = effectCallbackToCleanup.get(callback)) == null ? void 0 : _a();
effectCallbackToCleanup.delete(callback);
});
};
}
};
const notifyEffects = (value) => {
throwIfRefChanged(() => {
for (const [callback, cleanup] of effectCallbackToCleanup) {
cleanup();
effectCallbackToCleanup.set(callback, callback(value) ?? noop);
}
});
};
const proxy = new Proxy(rawManager, {
set: (target, propertyKey, value, receiver) => {
if (propertyKey === "current") {
invariant(!isInEffectRef.current, "Cannot change value of ref manager during effect");
target.current = value;
notifyEffects(value);
return true;
}
return Reflect.set(target, propertyKey, value, receiver);
}
});
return proxy;
});
return manager;
};
export {
useRefManager
};
//# sourceMappingURL=useRefManager.js.map