Open SeonHyungJo opened 4 years ago
const Hook = (function() { let hooks = [] let currentHook = 0 // Hook 배열과 반복자(iterator)! return { render(Component) { const Comp = Component() // 이펙트들이 실행된다. console.log('Check 2') Comp.render() currentHook = 0 // 다음 렌더를 위해 초기화 return Comp }, useEffect(callback, depArray) { const hasNoDeps = !depArray const deps = hooks[currentHook] // type: array | undefined const hasChangedDeps = deps ? !depArray.every((el, i) => el === deps[i]) : true console.log('Check useEffect', currentHook, hasNoDeps, hasChangedDeps) if (hasNoDeps || hasChangedDeps) { callback() hooks[currentHook] = depArray } currentHook++ // 이 Hook에 대한 작업 완료 }, useState(initialValue) { console.log('Check useState', hooks[currentHook] || initialValue) hooks[currentHook] = hooks[currentHook] || initialValue // type: any const setStateHookIndex = currentHook // setState의 클로저를 위해! const setState = (newState) => { hooks[setStateHookIndex] = newState } return [hooks[currentHook++], setState] }, } })() function Counter() { const [count, setCount] = Hook.useState(0) const [text, setText] = Hook.useState('foo') // 두번 째 상태 Hook! console.log('Check Create Component') Hook.useEffect(() => { console.log('Check Inner useEffect', count, text) }, [count, text]) return { click: () => setCount(count + 1), type: (txt) => setText(txt), noop: () => setCount(count), render: () => console.log('render', { count, text }), } } let App App = Hook.render(Counter) // App.click() // App.type('bar') App.noop() App = Hook.render(Counter) // App = Hook.render(Counter) // App.type('bar') // App = Hook.render(Counter) // App.noop() // App = Hook.render(Counter) // App.click() // App = Hook.render(Counter) // Hook은 데이터가 변경이 되면 render가 새로 돌면서 기존의 만들어진 것을 버리고 새로운 Counter를 만든다. // 만드는 과정에서 이전의 값을 보관하고 있기 위해서 Hook 객체 내부적으로 데이터를 가지고 있는다. // useState, useEffect는 데이터 변경감지고 render가 돌게 되면서 새로이 만든다. // 새로 만드는 과정에서 useEffect는 기존의 가지고 있던 데이터와 새로 들어온 데이터 하나하나를 비교해서 Callback()을 실행한다.