hooks灵感起源 hook.js
let info = null, schedule = new Set
const runSchedule = () => {
const previous = schedule
schedule = new Set
previous.forEach(({h, c, a, e}) => {
// avoid running schedules when the hook is
// re-executed before such schedule happens
if (e)
h.apply(c, a)
})
}
export const getInfo = () => info
export const isFunction = f => typeof f === 'function'
export const hooked = callback => {
const current = {h: hook, c: null, a: null, e: 0, i: 0, s: []}
return hook
function hook() {
const prev = info
info = current
current.e = current.i = 0
try {
return callback.apply(current.c = this, current.a = arguments)
}
finally {
info = prev
}
}
}
export const reschedule = info => {
if (!schedule.has(info)) {
info.e = 1
schedule.add(info)
wait.then(runSchedule)
}
}
export const wait = new Promise($ => $())
hooks灵感开天辟地reducer.js
import { getInfo, isFunction, reschedule } from './hooks.js'
const getValue = (value, f) => isFunction(f) ? f(value) : f
export const useReducer = (reducer, value, init) => {
const info = getInfo()
const {i, s} = info
if (i === s.length)
s.push({
$: isFunction(init) ?
init(value) : getValue(void 0, value),
set: value => {
s[i].$ = reducer(s[i].$, value)
reschedule(info)
}
})
const {$, set} = s[info.i++]
return [$, set]
}
export const useState = value => useReducer(getValue, value)
export const useRef = current => {
const info = getInfo()
const {i, s} = info
if (i === s.length)
s.push({current})
return s[info.i++]
}
hooks灵感盘古开创counter.js
import { hooked } from './hooks.js'
import { useState, useRef } from './reducer.js'
const Counter = (start) => {
const [count, setCount] = useState(start)
const {current} = useRef({})
current.increment = () => {
setCount(count + 1)
}
console.log(count)
return current
}
// logs 1, 1
const comp1 = hooked(Counter)(1)
const comp2 = hooked(Counter)(1)
// logs 2
comp1.increment()