Created
January 4, 2021 17:50
-
-
Save WebReflection/77b005e5693cf5e5c1fa1ea781b673d8 to your computer and use it in GitHub Desktop.
Revisions
-
WebReflection created this gist
Jan 4, 2021 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,103 @@ // WARNING: There's much more to know/do around hooks, and // this is just a simplification of how these work. // shared references, updated // per each hook invoke let execution = null; let current = null; let context = null; let args = null; // returns a function that updates known // references each time it gets executed // so that using useState within such function // can retrieve all details related to the hook const hooked = callback => { // create a stack to incrementally retrieve // or add new states whenever it's needed const details = {i: 0, stack: []}; // return the hook function that resets index, // update shared references, and then executes return function hook() { // reset the stack index details.i = 0; // update shared references execution = details; current = hook; context = this; args = arguments; // invoke the original callback return callback.apply(context, args); }; }; // every time a hook invokes a useState // the initial value is either known or new const useState = value => { // trap in this closure current details // so that it's possible to re-invoke the hook // with latest provided context and arguments const hook = current; const ctx = context; const rest = args; // grab current stack and its index const {i, stack} = execution; // increment the stack index so that the next // useState(value) will get its slot execution.i++; // if the stack does not know about this slot if (i === stack.length) { // store the initial value in the stack, // making the current stack[i] reachable stack.push(value); } return [ // the last value stored at this index // or the one we've just pushed stack[i], // the update function that re-invoke the hook value => { // update this stack value with a new one stack[i] = value; // execute the hook one more time, // so that everything gets synchronized hook.apply(ctx, rest); // this will repeat this recursive dance // until no state update happens } ]; }; // EXAMPLE - Counter factory // the hooked callback can be defined a part // as long as it's invoked only once hooked const toBeWrapped = start => { const [num, update] = useState(start); console.log(`Counting: ${num}`); setTimeout(update, 1000, num + 1); }; // in this case the Counter returns, each time, // a new hooked version of the same callback // and it executes it right away function Counter() { return hooked(toBeWrapped).apply(this, arguments); } // read a counting from 0 to N in console Counter(0);