“This is the 28th day of my participation in the November Gwen Challenge. See details of the event: The Last Gwen Challenge 2021”.
Reacthooks.js exports many of the built-in hook functions, and readers can read with this question in mind.
Take the useState hook function for example
export function useState<S> (
initialState: (() => S) | S,
) :S.Dispatch<BasicStateAction<S> >]{
const dispatcher = resolveDispatcher();
return dispatcher.useState(initialState);
}
Copy the code
useState
The hook function takes an input parameter ofinitialState
, which is the initialization state.- The current dispatcher is first found using the resolveDispatcher method.
- A call to the method on the dispatcher of a particular lifecycle returns the result of the call to this function, which returns an array with the first element being the state and the second element being the state-changing function, which is called internally
setState
.
Parse the dispatcher at different stages
function resolveDispatcher() {
const dispatcher = ReactCurrentDispatcher.current;
return dispatcher;
}
Copy the code
React has different life cycles. React calls different dispatchers when updating various payloads such as component states. ResolveDispatcher retrieves the current dispatcher via the current property of the global variable ReactCurrentDispatcher. This dispatcher includes various internal methods of the React hook function, such as useState.
How does the useState method work internally
function mountState(initialState) {
const hook = mountWorkInProgressHook();
hook.memoizedState = hook.baseState = initialState;
const queue = {
pending: null.interleaved: null.lanes: NoLanes,
dispatch: null.lastRenderedReducer: basicStateReducer,
lastRenderedState,
};
hook.queue = queue;
const dispatch= (queue.dispatch = (dispatchSetState.bind(
null,
currentlyRenderingFiber,
queue,
)));
return [hook.memoizedState, dispatch];
}
Copy the code
Whenever you call useState, you call useState for the current trigger, and useState for the current trigger will call methods at different stages of the cycle. For example, after mounting this stage, the mountState method is called and initialState is passed in.
The right way won’t work
It’s a little tricky to explain in order. So let’s do it backwards.
The bind() method creates a new function, and when bind() is called, this of the new function is specified as the first argument to bind(), and the remaining arguments will be used as arguments to the new function. From (MDN)
- First, the dispatchSetState method retrieves the current running Fiber fabric. The entire page is woven from the React fabric.
- This method will change the internal state of the fabric
state
This process pushes inUpdate the queue. - The current rendered fabric and queue presets are passed to the second element of the hook function’s return array using the bind method. The key here is to hook the fabric to the function component in this way.
- The dispatch variable is the value that our hook function returns. The dispatch variable applies the Dispatch property of queue, and the queue.dispatch property applies the bind function, so hook. Queue actually has a dispatch method.
Black-box operation
The two internal variables, hook and queue, seem to be defined only internally; they are not for external use and are not used internally. React authors define useless hook and queue variables. Okay, here’s the key code.
const hook = mountWorkInProgressHook();
// workInProgressHook
Copy the code
The function that generates the hook uses an internal global variable to save the current hook. The hook caches some history to optimize performance. After the hook. Queue attribute is assigned, a loop calls the methods in the queue. Look at the updateWork in Progress Shook method.
Thank you for reading, and if you find it inspiring, feel free to give it a thumbs up.