[React 까보기] 4. useState 의 구현체

이전 포스팅(3. Hook 구현체 찾아가기) 에서 renderWithHooks 내부의
ReactCurrentDispatcher.current = HooksDispatcherOnMount 를 확인하였고,
HooksDispatcherOnMount 에서 mountState를 발견하였다. 이때 mountState를 분석하면
아래에 나올 hook, queue, update 객체를 살펴볼 수 있다.

0️⃣ mountState()

function mountState<S>(
  initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
  // 1번
  const hook = mountWorkInProgressHook();
  
  // 초기 state
  if (typeof initialState === 'function') {
    initialState = initialState();
  }
  hook.memoizedState = hook.baseState = initialState;
  
  // 2번
  const queue = (hook.queue = {
    last: null,
    dispatch: null,
    lastRenderedReducer: basicStateReducer,
    lastRenderedState: (initialState: any),
  });
  
  const dispatch: Dispatch<
    BasicStateAction<S>,
  > = (queue.dispatch = (dispatchAction.bind(
    null,
    // Flow doesn't know this is non-null, but we do.
    ((currentlyRenderingFiber: any): Fiber),
    queue,
  ): any));
  
  // [state, setState] 의 형태
  return [hook.memoizedState, dispatch];
}

 

 1️⃣ hook 객체 - mountWorkInProgressHook()

function mountWorkInProgressHook():Hook {
	const hook:Hook = {
    	memoizedState: null, // 마지막에 얻은 state 값
        
        baseState: null,
        queue: null, // 하나의 hook 객체는 하나의 queue객체를 가짐
        baseUpdate: null,
        
        next: null, // 다음 훅에 할당될 키 값 (Fiber 안에 hook으로 Linked List의 형태로 연결되어 있음)
    };
    
    // 작업중인 훅이 없을때 -> 첫번째 훅 추가
    if(workInProgressHook = null){
    	firstWorkInProgressHook = workInProgress = hook;
    }
    // 작업중인 훅이 있을때 -> 새로운 훅 추가
    else{
    	workInProgressHook = workInProgress.next = hook; // linked list 형태로 훅 연결
    }
    
    // 위에서 생성한 hook 객체를 리턴하는 것과 같음
    // mountState 함수의 hook에 할당됨
    return workInProgressHook;
}

 

2️⃣ queue, update 객체

 // hook.queue에 같이 할당되어있음
 const queue = (hook.queue = {
    last: null, // 큐의 마지막 update 객체 (큐 안에 담겨있는 값은 update 객체들임)
    dispatch: null, 
    lastRenderedReducer: basicStateReducer,
    lastRenderedState: (initialState: any),
  });
  
  // 큐에 update 객체를 추가하는 함수
  const dispatch: Dispatch<
    BasicStateAction<S>,
  > = (queue.dispatch = (dispatchAction.bind( // 작업중인 fiber, queue를 바인딩 함
    null,
    ((currentlyRenderingFiber: any): Fiber),
    queue,
  ): any));


📚 레퍼런스