Skip to content

Instantly share code, notes, and snippets.

@ProdigySim
Last active August 7, 2020 14:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ProdigySim/c6bb7f7a45489f0331a4b622646cc2fc to your computer and use it in GitHub Desktop.
Save ProdigySim/c6bb7f7a45489f0331a4b622646cc2fc to your computer and use it in GitHub Desktop.
Thinking about making hooks a language generic feature supported by transpilation
// Stateful object used to track hook execution order
class HookStack {
private stack: unknown[]
private stackPtr: number = 0;
private isInitialStack: boolean;
constructor(stackMemo?: unknown[]) {
if (stackMemo) {
this.stack = [...stackMemo];
this.isInitialStack = true;
} else {
this.stack = [];
this.isInitialStack = false;
}
}
getOrCreateSlot<T>(fn: () => T): T {
if (this.stackPtr < this.stack.length) {
return this.stack[this.stackPtr++] as T;
}
if (this.isInitialStack) {
const newSlot = fn();
this.stack.push(newSlot);
this.stackPtr++;
return newSlot;
}
throw new Error("Please don't use hooks in conditionals and stuff.")
}
}
function useState_raw<T>(stack: HookStack, intiialValue: T) {
const slot = stack.getOrCreateSlot(() => {
return { value: intiialValue };
});
return [slot.value, (newValue: T) => slot.value = newValue] as const;
}
// Language transforms function to this signature
declare function useState<T>(initialValue: T): [T, (val: T) => void];
const MyComponentA = () => {
const [count, setCount] = use useState(0);
return <button onClick={ () => setCount(count+1) }>{ count }</button>;
}
// Language compiles function down to this:
const MyComponentA_comp = (() => {
// component "memory" storage
const memoStack: unknown[] = [];
const body = (stack: HookStack) => {
const [count, setCount] = useState_raw(stack, 0);
return <button onClick={ () => setCount(count+1) }>{ count }</button>;
};
return (..args) => body(new HookStack(memoStack), ...args)
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment