mini-react-dom
Version:
A lightweight React-like DOM renderer with JSX, hooks, context, SSR and lazy support
61 lines (47 loc) • 1.23 kB
JavaScript
let hooks = [];
let effects = [];
let currentHook = 0;
let currentEffect = 0;
export function resetHooks() {
currentHook = 0;
currentEffect = 0;
}
export function useState(initial) {
const i = currentHook;
hooks[i] = hooks[i] ?? initial;
const setState = (newVal) => {
hooks[i] = newVal;
rerender();
};
currentHook++;
return [hooks[i], setState];
}
export function useEffect(callback, deps) {
const old = effects[currentEffect];
const hasChanged =
!old || deps.some((dep, i) => !Object.is(dep, old.deps[i]));
if (hasChanged) {
setTimeout(callback);
effects[currentEffect] = { deps };
}
currentEffect++;
}
export function useMemo(factory, deps) {
const i = currentHook;
const prev = hooks[i];
const hasChanged =
!prev || deps.some((dep, idx) => !Object.is(dep, prev.deps[idx]));
if (hasChanged) {
hooks[i] = { value: factory(), deps };
}
currentHook++;
return hooks[i].value;
}
export function useCallback(callback, deps) {
// useCallback is just useMemo with the callback as the factory
return useMemo(() => callback, deps);
}
let rerender = () => console.warn("rerender not assigned yet");
export function setRerender(fn) {
rerender = fn;
}