-
Notifications
You must be signed in to change notification settings - Fork 10
/
hooks.js
73 lines (64 loc) · 2.74 KB
/
hooks.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
let globalHooksReplacer = {};
export const useState = (...args) => globalHooksReplacer.useState(...args);
// compares state changes between updates
const isStatesDiffer = (prev, next) => {
if (typeof next === 'object') {
return JSON.stringify(prev) !== JSON.stringify(next);
}
return prev !== next;
};
// Creates the unique useState for each component element.
// onUpdate should be called after state update to re-render the DOM.
// hooksMap contains each hook in relation to its VDOM pointer.
// VDOMPointer is specific per component.
const createMakeUseState =
(onUpdate, hooksMap) => (VDOMPointer, isFirstRender) => {
// START HERE
// Think about where you want to store the state so that it can be retrieved
// during the renders?
// this is what gets called in the React component when you use useState()
return initialState => {
if (isFirstRender) {
// In React, initialState can be a function for lazy state initilisation
// So to handle that, we should call the initialState if it's a function
const computedInitialState =
typeof initialState === 'function' ? initialState() : initialState;
const setState = newStateOrCb => {
const newStateFn =
typeof newStateOrCb === 'function'
? newStateOrCb
: () => newStateOrCb;
// DON'T FORGET
// We will need the previous state to calculate the next state
// if the developer used the callback style of setState
const currentState = newStateFn(previousState);
// DON'T FORGET
// We need to store the currentState
// So that it can be returned in the future render
// And we need to re-render after a state update
};
return [computedInitialState, () => 'replace this function'];
}
};
};
// Higher-Order Function that replaces hooks so they know which component
// they relate to (at the specified VDOMPointer)
const makeRegisterHooks =
(hooksMap, makeUseState) => (VDOMPointer, isFirstRender) => {
if (isFirstRender) {
hooksMap[VDOMPointer] = {};
}
const useState = makeUseState(VDOMPointer, isFirstRender);
globalHooksReplacer.useState = useState;
};
export const createHooks = onUpdate => {
// hooksMap[[0,0,0]] is the hooks for the component with VDOMPointer [0, 0, 0]
// Each value (hook) e.g. hooksMap[[0,0,0]] has the following structure { state: [], effect: []}
const hooksMap = {};
const hooks = { current: null };
const boundOnUpdate = () => onUpdate(hooks.current);
const makeUseState = createMakeUseState(boundOnUpdate, hooksMap);
const registerHooks = makeRegisterHooks(hooksMap, makeUseState);
hooks.current = { registerHooks };
return hooks.current;
};