在了解其他hook的实现后,理解useMemo与useCallback的实现非常容易。
本节我们以mount与update两种情况分别讨论这两个hook。
mount
function mountMemo<T>(nextCreate: () => T,deps: Array<mixed> | void | null,): T {// 创建并返回当前hookconst hook = mountWorkInProgressHook();const nextDeps = deps === undefined ? null : deps;// 计算valueconst nextValue = nextCreate();// 将value与deps保存在hook.memoizedStatehook.memoizedState = [nextValue, nextDeps];return nextValue;}function mountCallback<T>(callback: T, deps: Array<mixed> | void | null): T {// 创建并返回当前hookconst hook = mountWorkInProgressHook();const nextDeps = deps === undefined ? null : deps;// 将value与deps保存在hook.memoizedStatehook.memoizedState = [callback, nextDeps];return callback;}
可以看到,与mountCallback这两个唯一的区别是
mountMemo会将回调函数(nextCreate)的执行结果作为value保存mountCallback会将回调函数作为value保存
update
function updateMemo<T>(nextCreate: () => T,deps: Array<mixed> | void | null,): T {// 返回当前hookconst hook = updateWorkInProgressHook();const nextDeps = deps === undefined ? null : deps;const prevState = hook.memoizedState;if (prevState !== null) {if (nextDeps !== null) {const prevDeps: Array<mixed> | null = prevState[1];// 判断update前后value是否变化if (areHookInputsEqual(nextDeps, prevDeps)) {// 未变化return prevState[0];}}}// 变化,重新计算valueconst nextValue = nextCreate();hook.memoizedState = [nextValue, nextDeps];return nextValue;}function updateCallback<T>(callback: T, deps: Array<mixed> | void | null): T {// 返回当前hookconst hook = updateWorkInProgressHook();const nextDeps = deps === undefined ? null : deps;const prevState = hook.memoizedState;if (prevState !== null) {if (nextDeps !== null) {const prevDeps: Array<mixed> | null = prevState[1];// 判断update前后value是否变化if (areHookInputsEqual(nextDeps, prevDeps)) {// 未变化return prevState[0];}}}// 变化,将新的callback作为valuehook.memoizedState = [callback, nextDeps];return callback;}
可见,对于update,这两个hook的唯一区别也是是回调函数本身还是回调函数的执行结果作为value。
