유튜브에 React 까보기 시리즈 라는 영상으로 스터디를 진행하며 의미있는 강의는 자주 정리해 보려고 합니다.
강의를 찍으신 시점과 제가 학습하는 시점에 차이가 발생해 React 라이브러리의 코드가 다소 변화되었습니다. 이 글을 읽는 시점에도 코드가 다를 수 있음을 알려 드립니다.
//react/packages/react-reconciler/src/ReactFiberHooks.js
//159번줄
const {ReactCurrentDispatcher, ReactCurrentBatchConfig} = ReactSharedInternals;
renderWithHooks
함수에서 조건에 따라 HooksDispatcherOnMount
와 HooksDispatcherOnUpdate
이 결정된다.//react/packages/react-reconciler/src/ReactFiberHooks.js
//476번줄
export function renderWithHooks<Props, SecondArg>(
...
if (__DEV__) {
if (current !== null && current.memoizedState !== null) {
ReactCurrentDispatcher.current = HooksDispatcherOnUpdateInDEV;
} else if (hookTypesDev !== null) {
// This dispatcher handles an edge case where a component is updating,
// but no stateful hooks have been used.
// We want to match the production code behavior (which will use HooksDispatcherOnMount),
// but with the extra DEV validation to ensure hooks ordering hasn't changed.
// This dispatcher does that.
ReactCurrentDispatcher.current = HooksDispatcherOnMountWithHookTypesInDEV;
} else {
ReactCurrentDispatcher.current = HooksDispatcherOnMountInDEV;
}
} else {
ReactCurrentDispatcher.current =
current === null || current.memoizedState === null
? HooksDispatcherOnMount
: HooksDispatcherOnUpdate;
}
current === null || current.memoizedState === null
이 된다면 Mount 해야하며, 아닐경우 Update 일경우로 생각//react/packages/react-reconciler/src/ReactFiberHooks.js
//3470번줄
const HooksDispatcherOnMount: Dispatcher = {
readContext,
use,
useCallback: mountCallback,
useContext: readContext,
useEffect: mountEffect,
useImperativeHandle: mountImperativeHandle,
useLayoutEffect: mountLayoutEffect,
useInsertionEffect: mountInsertionEffect,
useMemo: mountMemo,
useReducer: mountReducer,
useRef: mountRef,
useState: mountState,
useDebugValue: mountDebugValue,
useDeferredValue: mountDeferredValue,
useTransition: mountTransition,
useSyncExternalStore: mountSyncExternalStore,
useId: mountId,
};
const HooksDispatcherOnUpdate: Dispatcher = {
readContext,
use,
useCallback: updateCallback,
useContext: readContext,
useEffect: updateEffect,
useImperativeHandle: updateImperativeHandle,
useInsertionEffect: updateInsertionEffect,
useLayoutEffect: updateLayoutEffect,
useMemo: updateMemo,
useReducer: updateReducer,
useRef: updateRef,
useState: updateState,
useDebugValue: updateDebugValue,
useDeferredValue: updateDeferredValue,
useTransition: updateTransition,
useSyncExternalStore: updateSyncExternalStore,
useId: updateId,
};
//react/packages/react-reconciler/src/ReactFiberHooks.js
//476번줄
export function renderWithHooks<Props, SecondArg>(
current: Fiber | null,
workInProgress: Fiber ... ): any {
renderLanes = nextRenderLanes;
**currentlyRenderingFiber = workInProgress; <- 이 코드가 핵심**
updateWorkInProgressHook
함수에서 사용=== null || current.memoizedState === null
로 대체된다.// 572번
let children = Component(props, secondArg);
// **업데이트 정보를 스케쥴러와 패키지에게 전달 했음?을 확인 -> Mount 일경우는 false**
if (didScheduleRenderPhaseUpdateDuringThisPass) {
// Keep rendering until the component stabilizes (there are no more render
// phase updates).
children = renderWithHooksAgain(
workInProgress,
Component,
props,
secondArg,
);
}
// 607번
function finishRenderingHooks<Props, SecondArg>(
current: Fiber | null,
workInProgress: Fiber,
Component: (p: Props, arg: SecondArg) => any,
): void {
// **이것을 왜?**
ReactCurrentDispatcher.current = ContextOnlyDispatcher;
const didRenderTooFewHooks =
currentHook !== null && currentHook.next !== null;
renderLanes = NoLanes;
currentlyRenderingFiber = (null: any);
currentHook = null;
workInProgressHook = null;
ReactCurrentDispatcher.current = ContextOnlyDispatcher;
이 코드가 의미하는 것은 ReactCurrentDispatcher.current를 재할당 하는 것이 아니라 위에서 컴포넌트를 호출한 뒤 더 이상 Hook을 요청해서는 안될때 Error를 알려주기 위함을 의미//3432번줄
export const ContextOnlyDispatcher: Dispatcher = {
readContext,
use,
useCallback: throwInvalidHookError,
useContext: throwInvalidHookError,
useEffect: throwInvalidHookError,
useImperativeHandle: throwInvalidHookError,
useInsertionEffect: throwInvalidHookError,
useLayoutEffect: throwInvalidHookError,
useMemo: throwInvalidHookError,
useReducer: throwInvalidHookError,
useRef: throwInvalidHookError,
useState: throwInvalidHookError,
useDebugValue: throwInvalidHookError,
useDeferredValue: throwInvalidHookError,
useTransition: throwInvalidHookError,
useSyncExternalStore: throwInvalidHookError,
useId: throwInvalidHookError,
};
function throwInvalidHookError() {
throw new Error(
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
' one of the following reasons:\n' +
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
'2. You might be breaking the Rules of Hooks\n' +
'3. You might have more than one copy of React in the same app\n' +
'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.',
);
}
// 926번줄
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;
}
// 1750번
function mountStateImpl<S>(initialState: (() => S) | S): Hook {
const hook = mountWorkInProgressHook();
if (typeof initialState === 'function') {
const initialStateInitializer = initialState;
// $FlowFixMe[incompatible-use]: Flow doesn't like mixed types
initialState = initialStateInitializer();
if (shouldDoubleInvokeUserFnsInHooksDEV) {
setIsStrictModeForDevtools(true);
// $FlowFixMe[incompatible-use]: Flow doesn't like mixed types
initialStateInitializer();
setIsStrictModeForDevtools(false);
}
}
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;
return hook;
}
function mountState<S>(
initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
const hook = mountStateImpl(initialState);
const queue = hook.queue;
const dispatch: Dispatch<BasicStateAction<S>> = (dispatchSetState.bind(
null,
currentlyRenderingFiber,
queue,
): any);
queue.dispatch = dispatch;
return [hook.memoizedState, dispatch];
}
///607 번줄
function finishRenderingHooks<Props, SecondArg>(
current: Fiber | null,
workInProgress: Fiber,
Component: (p: Props, arg: SecondArg) => any,
): void {
if (__DEV__) {
workInProgress._debugHookTypes = hookTypesDev;
}
// We can assume the previous dispatcher is always this one, since we set it
// at the beginning of the render phase and there's no re-entrance.
ReactCurrentDispatcher.current = ContextOnlyDispatcher;
// This check uses currentHook so that it works the same in DEV and prod bundles.
// hookTypesDev could catch more cases (e.g. context) but only in DEV bundles.
const didRenderTooFewHooks =
currentHook !== null && currentHook.next !== null;
renderLanes = NoLanes;
currentlyRenderingFiber = (null: any);
currentHook = null;
workInProgressHook = null;
Wonderful posting, Thanks a ton to get spreading The following awareness. Wonderfully authored posting, doubts all of blog owners available precisely the same a higher standard subject material just like you, online has got to be improved site. I highly recommend you stay the best! łóżka piętrowe
Wonderful posting, Thanks a ton to get spreading The following awareness. Wonderfully authored posting, doubts all of blog owners available precisely the same a higher standard subject material just like you, online has got to be improved site. I highly recommend you stay the best! endones
This really is therefore stunning as well as innovative. I simply adore the actual colours as well as whomever will get this within the postal mail is going to be grinning.잠실 가라오케
With thanks just for offer a very awesome page! I stubled onto a web site ideal for great really needs. Its content has delightful and additionally important reports. Preserve acknowledge that there are succeed! 押上 英会話
Seriously sturdy, magnificent, fact-filled information and facts listed here. A person's discussions Never need disappoint, and the unquestionably is valid listed here in addition. You actually continually make a fun learn. Do you convey to I'm just happy?: )#) Keep up to date the nice reports. Best personal trainers in Orlando
阿拉斯加以壮丽的冰川、极光和丰富的野生动物闻名。游客可游览迪纳利国家公园、冰川湾,体验狗拉雪橇、冰川徒步和观鲸等活动。冬季可欣赏绚丽极光,夏季则可享受极昼奇观,是大自然爱好者的天堂 拉 斯 維 加 斯 景點
That is the excellent mindset, nonetheless is just not help to make every sence whatsoever preaching about that mather. Virtually any method many thanks in addition to i had endeavor to promote your own article in to delicius nevertheless it is apparently a dilemma using your information sites can you please recheck the idea. thanks once more. slot gacor hari ini
I recently considered it could be a thought to create could someone else has been having troubles exploring yet I will be slightly not sure easily feel allowed to set brands and also address about the following. 은평 직장인 대출
Many thanks regarding submitting this kind of fantastic write-up! I came across your internet site perfect for my own wants. It includes great and also beneficial content. Maintain the nice perform! Eliran Mor
Seriously! What exactly a close watch opener that write-up has become in my opinion. Completely liked, book-marked, When i can’t lose time waiting for far more! koitoto Seriously! What exactly a close watch opener that write-up has become in my opinion. Completely liked, book-marked, When i can’t lose time waiting for far more! olxtoto Seriously! What exactly a close watch opener that write-up has become in my opinion. Completely liked, book-marked, When i can’t lose time waiting for far more! olxtoto Seriously! What exactly a close watch opener that write-up has become in my opinion. Completely liked, book-marked, When i can’t lose time waiting for far more! koi toto Seriously! What exactly a close watch opener that write-up has become in my opinion. Completely liked, book-marked, When i can’t lose time waiting for far more! Skrota bilen
I am incapable of reading articles online very often, but I’m happy I did today. It is very well written, and your points are well-expressed. I request you warmly, please, don’t ever stop writing. Satta king
Wow, cool post. I’d like to write like this too – taking time and real hard work to make a great article… but I put things off too much and never seem to get started. Thanks though. สล็อตเว็บตรง
Wow, cool post. I’d like to write like this too – taking time and real hard work to make a great article… but I put things off too much and never seem to get started. Thanks though. esports lawyers
I was reading some of your content on this website and I conceive this internet site is really informative ! Keep on putting up.olxtoto loginSkrotbilarnaBlanca City by Sun Grouphttps://www.sshh.uk.com/toto macauolxtoto login
I’m moved considering the surpassing and even preachy index that you really generate such modest timing. łóżeczko dla dziecka