useState 뜯어보기 1편에서는
ReactCurrentDispatcher.current
의 값으로 인해서 useState의 반환값이 정해진다는 걸 알 수 있었다. 그럼ReactCurrentDispatcher.current
에는 어떠한 값들이 정의된 것이고 내부 로직은 어떻게 동작할까?
먼저
ReactCurrentDispatcher
는 ReactSharedInternals
객체변수로 관리되고 있다.
ReactSharedInternals
객체는 react-reconciler/src
디렉토리 안에 있는 ReactFiberHooks.js
파일 내부에서 import되어 사용하고 있다.
import한
ReactSharedInternals
를 객체구조분해를 통해 ReactCurrentDispatcher
변수를 정의한 걸 확인할 수 있다.
객체구조분해하여 정의한
ReactCurrentDispatcher
변수의 current
는 분기문에 의해서 HooksDispatcherOnMount
혹은 HooksDispatcherOnUpdate
변수에 정의한 걸 확인할 수 있다.
HooksDispatcherOnMount
변수를 따라가보면 객체 안에 mountState
변수가 useState
로 사용되고 있다는 걸 확인 할 수 있다.
useState
훅 말고도 다른 훅들이 정의되어 있다는 것도 확인할 수 있다.
결국 우리가 실질적으로 사용하는 useState
훅의 원본은 mountState
인 것이다.
"mountState"에서 반환하는
[ hooks.memoizedState, dispatch ]
값이 바로 우리가 useState
훅에서 반환된 배열 값이다.
여기서 "hooks"는 mountStateImpl
에 "initialState"즉, 초기값을 넘겨 받아 반환되는 값이다.
mountStateImpl
을 보면 다시 "hook"은 mountWorkInProgressHook
함수의 반환값으로 정의된다.
mountWorkInProgressHook
에서는 memoizedState, baseState, queue, next
가 있는 객체를 할당한다.
여기서 memoizedState
는 컴포넌트에 적용된 마지막 state 값이다.
즉, 우리가 useState
를 통해서 반환받는 배열의 0번째 원소인 상태값을 의미하는 것이다.
next
는 workInProgressHook
이 있을 때 다음 hook
을 가르키는 포인터이다.
즉, 여러개의 state가 호출된다면 순차적으로 실행되는 이유가 연결리스트에 훅들이 순차적으로 연결되어 있어서 다음 훅을 호출할 수 있는 것이다.
queue
는 단일 훅이 여럽너 호출될 경우 저장되는 용도이다.
이번 포스팅을 통해서 useState훅이 내부적으로 어떻게 동작하고 연속적으로 훅이 호출될 시 어떻게 어떤식으로 저장해서 사용하는지 확인해볼 수 있었다.
물론 useState의 상태값에 따라서 컴포넌트가 렌더링 되는 내부로직 까지는 살펴보지 못했지만 해당 부분은 더 공부 한 후에 포스팅 할 예정이다.
참고로 npx creat-react-app
으로 React 프로젝트를 설치하면 "ReactFiberHooks.js"파일을 node_modules에서 찾지 못한다.
해당 파일을 확인하려면 react-reconciler
패키지를 따로 설치해서 확인하거나 혹은 "node_modules"디렉토리에 있는 react
디렉토리 "package.json"파일에 있는 "repository"에 있는 url을 통해서 확인해야 한다.
Reference의 맨 아래 부분에 해당 링크로 접근해도 된다.
https://www.youtube.com/watch?v=7mU7ARgrpfI&t=246s
https://kyoung-jnn.com/posts/react-useState
https://velog.io/@chaeerim/Too-many-re-renders-%EC%97%90%EB%9F%AC%EB%8A%94-%EC%99%9C-%EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94-%EA%B2%83%EC%9D%BC%EA%B9%8C
https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberHooks.js