 
                useState는 어떻게 구현이 되었을까?
면접 질문으로 받은 질문이다.
정말 단순한 예상으로는 아래와 같이 구현이 되었을 것이라 생각을 하지만 실제 구현은 어떻게 되었는지 모르고 있다.
const useState = (state) => {
	let state = value;
	const setState = (newValue) => {
		if(Object.is(state, newValue) return;
		state = newValue;
		// render를 불러일으키는 함수
	}
	return [state, setState];
};Behind the hood implementation of useState react hook
위 포스트에서는 다음과 같이 simplified 한 구현을 보이고 있다.
모듈 레벨의 clojure 인 것으로 추측된다.
let componentHooks = []
let currentHookIndex = 0
// How useState works inside React (simplified).
function useState(initialState) {
    let pair = componentHooks[currentHookIndex]
    if (pair) {
        // This is not the first render,
        // so the state pair already exists.
        // Return it and prepare for next Hook call.
        currentHookIndex++
        return pair
    }
    // This is the first time we're rendering,
    // so create a state pair and store it.
    pair = [initialState, setState]
    function setState(nextState) {
        // When the user requests a state change,
        // put the new value into the pair.
        pair[0] = nextState
        updateDOM()
    }
    // Store the pair for future renders
    // and prepare for the next Hook call.
    componentHooks[currentHookIndex] = pair
    currentHookIndex++
    return pair
}그래도 무언가 부족한 것이 있는 것 같다.
React내의 구현
React 라이브러리에서는 다음과 같이 구현되어 있다.
export function useState<S>(
    initialState: (() => S) | S
): [S, Dispatch<BasicStateAction<S>>] {
    const dispatcher = resolveDispatcher()
    return dispatcher.useState(initialState)
}// react-reconciler\src\ReactFiberHook.new.js
// useState의 원형
function mountState<S>(
  initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
  const hook = mountWorkInProgressHook();
  if (typeof initialState === 'function') {
    // $FlowFixMe: Flow doesn't like mixed types
    initialState = initialState();
  }
	**// 기본적인 State는 hook에 저장된다.**
  **hook.memoizedState = hook.baseState = initialState;**
  const queue: UpdateQueue<S, BasicStateAction<S>> = {
    pending: null,
    lanes: NoLanes,
    dispatch: null,
    lastRenderedReducer: basicStateReducer,
    lastRenderedState: (initialState: any),
  };
  hook.queue = queue;
	**// bind 를 이용해 마지막 action 인자를 전달하지 않는다.
	// 이렇게 bind로 래핑한 dispatch 액션을 전달하게 된다.
	// 마지막 인자는 지연평가의 형태로 라이브러리를 사용하는
	// 개발자가 state값을 업데이트하기 위해 사용된다.**
  **const dispatch: Dispatch<
    BasicStateAction<S>,
  > = (queue.dispatch = (dispatchSetState.bind(
    null,
    currentlyRenderingFiber,
    queue,
  ): any));**
  return [hook.memoizedState, dispatch];
}
// 2번째 요소로 주어지는 setState dispatcher
function dispatchSetState<S, A>(
  fiber: Fiber,
  queue: UpdateQueue<S, A>,
  action: A,
) {
  if (__DEV__) {
    if (typeof arguments[3] === 'function') {
      console.error(
        "State updates from the useState() and useReducer() Hooks don't support the " +
          'second callback argument. To execute a side effect after ' +
          'rendering, declare it in the component body with useEffect().',
      );
    }
  }
  const lane = requestUpdateLane(fiber);
  const update: Update<S, A> = {
    lane,
    action,
    hasEagerState: false,
    eagerState: null,
    next: (null: any),
  };
  if (isRenderPhaseUpdate(fiber)) {
    enqueueRenderPhaseUpdate(queue, update);
  } else {
    const alternate = fiber.alternate;
    if (
      fiber.lanes === NoLanes &&
      (alternate === null || alternate.lanes === NoLanes)
    ) {
      // The queue is currently empty, which means we can eagerly compute the
      // next state before entering the render phase. If the new state is the
      // same as the current state, we may be able to bail out entirely.
      const lastRenderedReducer = queue.lastRenderedReducer;
      if (lastRenderedReducer !== null) {
        let prevDispatcher;
        if (__DEV__) {
          prevDispatcher = ReactCurrentDispatcher.current;
          ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;
        }
        try {
          const currentState: S = (queue.lastRenderedState: any);
          const eagerState = lastRenderedReducer(currentState, action);
          // Stash the eagerly computed state, and the reducer used to compute
          // it, on the update object. If the reducer hasn't changed by the
          // time we enter the render phase, then the eager state can be used
          // without calling the reducer again.
          update.hasEagerState = true;
          update.eagerState = eagerState;
          if (is(eagerState, currentState)) {
            // Fast path. We can bail out without scheduling React to re-render.
            // It's still possible that we'll need to rebase this update later,
            // if the component re-renders for a different reason and by that
            // time the reducer has changed.
            // TODO: Do we still need to entangle transitions in this case?
            enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update);
            return;
          }
        } catch (error) {
          // Suppress the error. It will throw again in the render phase.
        } finally {
          if (__DEV__) {
            ReactCurrentDispatcher.current = prevDispatcher;
          }
        }
      }
    }
    const root = enqueueConcurrentHookUpdate(fiber, queue, update, lane);
    if (root !== null) {
      const eventTime = requestEventTime();
      scheduleUpdateOnFiber(root, fiber, lane, eventTime);
      entangleTransitionUpdate(root, queue, lane);
    }
  }
  markUpdateInDevTools(fiber, lane, action);
}
//
function mountWorkInProgressHook(): Hook {
  const hook: Hook = {
    memoizedState: null,
    baseState: null,
    baseQueue: null,
    queue: null,
    next: null,
  };
  if (workInProgressHook === null) {
    // This is the first hook in the list
    currentlyRenderingFiber.memoizedState = workInProgressHook = hook;
  } else {
    // Append to the end of the list
    workInProgressHook = workInProgressHook.next = hook;
  }
  return workInProgressHook;
}간소화한다면 다음과 같이 나타낼 수 있을 것 같다.
const fiber= {
	memoizedState: null;
}
const lastHook = fiber.memoizedState;
const useState = (initialValue) => {
	const hook = createStateHook();
	const dispatcher = createStateDispatcher.bind(null, fiber, hook);
	return [hook, dispatcher];
};
const createStateHook = () => {
	const hook = {
		// 현재 state
		memoizedState: null,
		// 초기 state
		baseState: null,
		// 다음 hook
		next: null,
	};
	if(lastHook) {
		fiber.memoizedState = lastHook = hook;
	} else {
		lastHook = lastHook.next = hook;
	}
	return lastHook;
};
const createStateDispatcher = (renderingFiber, hook, action) => {
	if(Object.is(action, hook.memoizedState)) {
		// render dom
	}
};이제 React의 렌더링 과정을 알아볼 때가 된 것 같다.
Fiber가 무엇인지 궁금해졌다.
