Skip to content

Instantly share code, notes, and snippets.

@keller
Created April 23, 2019 21:49
Show Gist options
  • Save keller/4e2d884f1865db4153792069310ac57c to your computer and use it in GitHub Desktop.
Save keller/4e2d884f1865db4153792069310ac57c to your computer and use it in GitHub Desktop.
/* naive implementation of useState and useEffect */
let states = [];
let newStates;
let _render = () => {};
let unsubs = [];
let deps = [];
let newDeps;
const shallowEqual = (a, b) =>
a.length === b.length && a.every((e, i) => e === b[i]);
function useState(initial) {
let state = states.pop();
if (state === undefined) {
state = [initial];
}
newStates.push(state);
const setState = newState => {
state[0] = newState;
_render();
}
return [state[0], setState];
}
function useEffect(effect, effectDeps) {
const dep = deps.pop();
if (dep == null || effectDeps == null || (effectDeps.length > 0 && !(shallowEqual(effectDeps, dep)))) {
const unsub = effect();
if (unsub) {
unsubs.push(unsub);
}
}
newDeps.push(effectDeps);
}
function render(app) {
_render = () => {
unsubs.forEach(unsub => unsub());
unsubs = [];
newStates = [];
newDeps = [];
app();
states = newStates;
deps = newDeps;
};
_render();
}
/* the app */
function app() {
const [count, setCount] = useState(0);
const [count2, setCount2] = useState(0);
useEffect(() => {
const button = document.querySelector("button");
const onClick = () => {
setCount(count+1);
setCount2(count2+2);
}
button.addEventListener("click", onClick);
return () => {
button.removeEventListener("click", onClick);
}
}, [count, count2]);
const el1 = document.querySelector(".count1");
const el2 = document.querySelector(".count2");
el1.innerText = count;
el2.innerText = count2;
}
/* render it */
render(app);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment