hta
Version:
The tiny framework for building Hyper Text Application with ease
81 lines (78 loc) • 2.11 kB
JavaScript
import arrayEqual from "../core/arrayEqual";
import {EMPTY_ARRAY, FUNC, REF_HOOK} from "../core/types";
export default function createHookManager() {
let index = -1;
let currentCount = 0;
let prevCount = undefined;
let unsubscribeDestroyEvent;
let disposeCount = 0;
let hooks = [];
let updated = [];
return {
onUpdated(listener) {
updated[updated.length] = listener;
},
updated() {
for (let i = 0; i < updated.length; i++) updated[i]();
},
updating() {
if (typeof prevCount !== "undefined" && currentCount !== prevCount) {
throw new Error(
`Invalid hook usages. Previous: ${prevCount}, Current: ${currentCount}`
);
}
updated = [];
prevCount = currentCount;
index = -1;
},
ref(initial) {
index++;
let hook = hooks[index];
if (!hook) {
hooks[index] = hook = {
type: REF_HOOK,
value: {
current: typeof initial === FUNC ? initial() : initial,
},
};
}
return hook.value;
},
unmount() {
if (!disposeCount) return;
for (let i = 0; i < hooks.length; i++) {
if (typeof hooks[i].dispose === "function") {
hooks[i].dispose();
}
}
},
get(type, initial, deps = EMPTY_ARRAY) {
index++;
let hook = hooks[index];
if (hook) {
if (hook.type !== type) throw new Error("Invalid hook order");
// re-create hook if deps changed
if (
deps === false ||
hook.deps === false ||
!arrayEqual(hook.deps, deps)
) {
if (hook && hook.dispose) {
disposeCount--;
if (!disposeCount && unsubscribeDestroyEvent) {
unsubscribeDestroyEvent();
unsubscribeDestroyEvent = undefined;
}
hook.dispose();
}
hook = undefined;
}
}
if (!hook) {
hooks[index] = hook = { type, deps, ...initial() };
hook.dispose && disposeCount++;
}
return hook.result();
},
};
}