분석 순서
- 훅 구현체 찾아가기
- 훅은 어떻게 생성되는가? (마운트)
- 훅은 어떻게 상태를 변경하고 컴포넌트를 리-렌더링시키는가?
- 상태가 변경되어 리-렌더될 때 변경된 상태 값은 어떻게 가지고 오는 것일까?(업데이트)
훅을 사용할 때 훅을 코어 패키지에서 불러 오지만 실제 구현체는 외부 모듈에 있다, 따라서 분석의 시작은 코어가 어떻게 외부 모듈에 있는 훅 구현체를 가지고 와서 제공하는지부터 확인한다
1. 훅 구현체 찾아가기
1-1 Hook의 구현체는 어디에 있을까?
// react > React.js
import { useState, useEffect, ... } from './ReactHooks'
import ReactSharedInternals from './ReactSharedInternals'
// 의존성을 주입받는 징검다리
const React = {
useState,
useEffect,
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED : ReactSharedInternals,
/* ... */
}
export default React
- 개발자가 코어를 통해 가져오는 훅은
ReactHooks.js
모듈에서 가져오고 있다
// react > ReactHooks.js
import ReactCurrentDispatcher from './ReactCurrentDispatcher'
function resolveDispatcher() {
const dispatcher = ReactCurrentDispatcher.current
return dispatcher
}
export function useState(initialState) {
const dispatcher = resolveDispatcher()
return dispatcher.useState(initialState)
}
export function useEffect(create, inputs) {
const dispatcher = resolveDispatcher()
return dispatcher.useEffect(create, inputs)
}
/* ... */
- 우리가 사용하는 훅은
ReactCurrentDispatcher.js
모듈에서 가지고 온 dispatcher
의 메소드이다
// react > ReactCurrentDispatcher.js
const ReactCurrentDispatcher = {
current : null,
}
export default ReactCurrentDispatcher
- 코어는 컴포넌트의 모델인 React Element만 알고 있다
- 이 element를 인스턴스화 되기 전인 클래스라고 생각해보자면 훅은 이 클래스의 인스턴스화된 객체의 상태값을 관리하는 역할을 한다
- React element는 fiber로 확장되고 나서야 살아 숨쉬게 된다
- 이 역할은 reconciler가 가지고 있다
- 그러므로 훅 또한 reconciler가 알고 있다
- 리액트 코어를 보면 어디에도 reconciler에서 훅을 가져오는 부분을 확인하지 못했다
- 훅 객체를 외부에서 내부로 ReactCurrentDispatcher.current를 통해 주입해준다는 이야기다
- 이렇듯 코어는 다른 패키지의 기능을 개발자에게 제공해 줄 때 의존성을 자기가 만들지 않고 외부에서 주입 받는다 - 스프링의 DI