Hooks internally are implemented as a queue with each hook being represented by a node having the reference to the next one.
From the documentation:
There is an internal list of “memory cells” associated with each
component. They’re just JavaScript objects where we can put some data.
When you call a Hook like useState(), it reads the current cell (or
initializes it during the first render), and then moves the pointer to
the next one. This is how multiple useState() calls each get
independent local state.
The architecture would be similar to
{
memoizedState: 'A',
next: {
memoizedState: 'B',
next: {
memoizedState: 'C',
next: null
}
}
}
The schema of a single hook is as below. It can be found in the implementation
function createHook(): Hook {
return {
memoizedState: null,
baseState: null,
queue: null,
baseUpdate: null,
next: null,
};
}
The key properties that let hooks behave the way they are are memoizedState
and next
.
Before each and every function Component invocation, prepareHooks()
is gonna be called, where the current fiber and its first hook node in the hooks queue are gonna be stored in global variables. This way, any time we call a hook function (useXXX())
it would know in which context to run.
After the update finishHooks(
) will be called, where a reference for the first node in the hooks queue will be stored on the rendered fiber in the memoizedState
property
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…