Skip to content

Instantly share code, notes, and snippets.

@ProdigySim
Created July 1, 2019 18:48
Show Gist options
  • Select an option

  • Save ProdigySim/21663d3fd89562e9d55c8cce1772c405 to your computer and use it in GitHub Desktop.

Select an option

Save ProdigySim/21663d3fd89562e9d55c8cce1772c405 to your computer and use it in GitHub Desktop.
Here's my naiive assumption of how hooks are implemented.
let global_currentHooks: object[] | null = null;
let global_currentHookIndex: number | null = null;
function getNextHook() {
return global_currentHooks![global_currentHookIndex!];
}
const state = new Map();
function doRender(componentFn: () => string) {
// Setup the "global" hooks array, for our component to use.
global_currentHooks = state.get(componentFn) || [];
global_currentHookIndex = 0;
// Run the component's render function. It will call various hooks,
// which will operate on the global "currentHooks" array.
const res = componentFn();
// Save the state of these hooks back to our store.
state.set(componentFn, global_currentHooks);
global_currentHooks = null;
global_currentHookIndex = null;
return res;
}
type StateHookObject<T> = {
value: T,
updater: (v: T) => void,
};
function createStateHook<T>(initialValue: T) {
const obj = {
value: initialValue,
updater: (v: T) => { obj.value = v; },
}
global_currentHooks!.push(obj);
return obj;
}
function useState<T>(initialValue: T) {
const stateHook = getNextHook() as StateHookObject<T> || createStateHook(initialValue);
++global_currentHookIndex!;
return [stateHook.value, stateHook.updater] as const;
}
function MyComponent() {
const [count, updateCount] = useState(0);
setTimeout(() => updateCount(1));
return '<p>' + count + ' kittens</p>';
}
alert(doRender(MyComponent))
setTimeout(() => {
alert(doRender(MyComponent))
}, 1000);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment