SeonHyungJo / Tip-Note

:round_pushpin: 개발을 하면서 느끼고 알게된 Tip:round_pushpin:
7 stars 0 forks source link

React Hook 예제로 자세히 살펴보기 #47

Open SeonHyungJo opened 4 years ago

SeonHyungJo commented 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()을 실행한다.