Skip to content

Instantly share code, notes, and snippets.

@anthonybrown
Last active August 15, 2019 01:38
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 anthonybrown/fb1bedd72b95f534622a5a477a93d680 to your computer and use it in GitHub Desktop.
Save anthonybrown/fb1bedd72b95f534622a5a477a93d680 to your computer and use it in GitHub Desktop.
Using closures, higher order functions to have a stateful function
function getAdd() {
let foo = 0;
return function() {
foo = foo + 1;
return foo;
};
}
const add = getAdd()
console.log(add());
console.log(add());
console.log(add());
console.log(add());
console.log(add());
console.log(add());
const add = (function getAdd() {
let foo = 0;
return function() {
foo = foo + 1;
return foo;
};
}());
console.log(add());
console.log(add());
console.log(add());
console.log(add());
console.log(add());
console.log(add());
console.log(add());
console.log(add());
console.log(add());
console.log(add());
// basically creating a react component in JavaScript
const React = (function() {
let _val;
function useState(initVal) {
const state = _val || initVal;
const setState = newVal => {
_val = newVal;
};
return [state, setState];
}
function render(Component) {
const C = Component();
C.render();
return C;
}
return { useState, render };
})();
function Component() {
const [count, setCount] = React.useState(1);
return {
render: () => console.log(count),
click: () => setCount(count + 1),
};
}
var App = React.render(Component);
App.click();
var App = React.render(Component);
App.click();
var App = React.render(Component);
App.click();
var App = React.render(Component);
App.click();
var App = React.render(Component);
// console.log(count());
// setCount(2);
// console.log(count());
const React = (function() {
let hooks = [];
let idx = 0;
function useState(initVal) {
const state = hooks[idx] || initVal;
const _idx = idx;
const setState = newVal => {
hooks[_idx] = newVal;
};
idx++;
return [state, setState];
}
function render(Component) {
idx = 0;
const C = Component();
C.render();
return C;
}
function useEffect(cb, depArray) {
const oldDeps = hooks[idx];
let hasChanged = true;
if (oldDeps) {
hasChanged = depArray.some((dep, i) => !Object.is(dep, oldDeps[i]));
}
// detect change
if (hasChanged) cb();
hooks[idx] = depArray;
idx++;
}
return { useState, render, useEffect };
})();
function Component() {
// we have 2 hooks now
const [count, setCount] = React.useState(1);
const [text, setText] = React.useState('apple');
React.useEffect(() => {
console.log('use effect hook FTW!!!');
}, []); // if I leave the empty array, it only runs once at the start
// if I put in [count] it updates from 1 to 2
// if I put in ['pear'] it updates when the text updates from 'apple' to 'pear'
// and if I delete the array, it runs every single time.
return {
// just for simulating since we don't have a button or working with the DOM
render: () => console.log({ count, text }),
click: () => setCount(count + 1),
type: word => setText(word),
};
}
var App = React.render(Component);
App.click();
var App = React.render(Component);
App.type('pear');
var App = React.render(Component);
iconst React = (function() {
let hooks = [];
let idx = 0;
function useState(initVal) {
const state = hooks[idx] || initVal;
const _idx = idx;
const setState = newVal => {
hooks[_idx] = newVal;
};
idx++;
return [state, setState];
}
function render(Component) {
idx = 0;
const C = Component();
C.render();
return C;
}
return { useState, render };
})();
function Component() {
// we have 2 hooks now
const [count, setCount] = React.useState(1);
const [text, setText] = React.useState('apple');
return {
// just for simulating since we don't have a button or working with the DOM
render: () => console.log({ count, text }),
click: () => setCount(count + 1),
type: word => setText(word),
};
}
var App = React.render(Component);
App.click();
var App = React.render(Component);
App.type('pear');
var App = React.render(Component);
/**
* We now have 2 independent states in our code
* 1 to update the count and
* 2 to update the text
*/
function useState(initVal) {
let _val = initVal;
const state = () => _val;
const setState = newVal => {
_val = newVal;
};
return [state, setState];
}
const [count, setCount] = useState(1);
console.log(count());
setCount(2);
console.log(count());
setCount(3);
console.log(count());
@anthonybrown
Copy link
Author

From "Getting Closure on React Hooks" by Shawn Wang

@anthonybrown
Copy link
Author

anthonybrown commented Aug 15, 2019

The functions are out of order, but basically the longer the function is the order.
Meaning the shortest code is the start and the longest is the most recent.

¯_(ツ)_/¯

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment