There are two kinds of circumstances: mount and update, so useMemo has two implementations: mountMemo and updateMemo.
- The source code of mountMemo:
function mountMemo<T>(
nextCreate: () => T,
deps: Array<mixed> | void | null,
): T {
const hook = mountWorkInProgressHook();
const nextDeps = deps === undefined ? null : deps;
const nextValue = nextCreate();
if (shouldDoubleInvokeUserFnsInHooksDEV) {
setIsStrictModeForDevtools(true);
nextCreate();
setIsStrictModeForDevtools(false);
}
hook.memoizedState = [nextValue, nextDeps];
return nextValue;
}
Explanation:
In the mount phase, the useMemo
function calls the callback function to calculate and return the value. Save the value and deps into hook.memoizedState
.
Use
mountWorkInProgressHook
to create a hook object.Save deps in
nextDeps
.Call the
nextCreate()
to getnextValue
. If in a dev environment, call twice.Save the
nextValue
andnextDeps
in thehook.memoizedState
and returnnextValue
.
- The source code of updateMemo:
function updateMemo<T>(
nextCreate: () => T,
deps: Array<mixed> | void | null,
): T {
const hook = updateWorkInProgressHook();
const nextDeps = deps === undefined ? null : deps;
const prevState = hook.memoizedState;
// Assume these are defined. If they're not, areHookInputsEqual will warn.
if (nextDeps !== null) {
const prevDeps: Array<mixed> | null = prevState[1];
if (areHookInputsEqual(nextDeps, prevDeps)) {
return prevState[0];
}
}
const nextValue = nextCreate();
if (shouldDoubleInvokeUserFnsInHooksDEV) {
setIsStrictModeForDevtools(true);
nextCreate();
setIsStrictModeForDevtools(false);
}
hook.memoizedState = [nextValue, nextDeps];
return nextValue;
}
Explanation:
In the update phase, React will judge whether the deps
have changed or not, if changed, React will run the callback to get the new value and return. If not changed, React will return the old value.
- Get a new hook object:
hook = updateWorkInProgressHook()
; - if deps array is empty
if (nextDeps !== null)
, call the callback function every render and return new value. - If the deps array is not empty, judge whether the deps have changed or not
if (areHookInputsEqual(nextDeps, prevDeps))
. If not changed, return the old valuereturn prevState[0];
.
Top comments (0)