共计 1931 个字符,预计需要花费 5 分钟才能阅读完成。
这次来看 useCallback。useCallback 是所有原生 use 中比较简单的函数
其实整体跟 useRef/useState 相似。
咱们间接看源码。
初始化的时候,次要执行如下代码:
function mountCallback(callback, deps) {
// 获取以后钩子,也就是链表指针
var hook = mountWorkInProgressHook();
// deps 是 useCallback 的第二个参数,也就是什么状况下须要更新 callback
var nextDeps = deps === undefined ? null : deps;
// 两个值存到 hook.memoizedState,也是 hooks 这套代码的常见伎俩
hook.memoizedState = [callback, nextDeps];
// 返回 callback。就是传入什么,返回什么。return callback;
}
要害是第二次渲染 functional component 时做的事件:
function updateCallback(callback, deps) {
// 通用做法。var hook = updateWorkInProgressHook();
// 获取以后的依赖值,是一个数组
var nextDeps = deps === undefined ? null : deps;
// 获取之前的依赖值,用于比照的。也是一个数组,这个数组中 [1] 的值才是依赖值
var prevState = hook.memoizedState;
// 检测确定 prevState 存在。什么状况不存在?临时不晓得
if (prevState !== null) {
// 检测 nextDeps 存在。这一行和上一行的判断是能够合并的。if (nextDeps !== null) {// 后面说道,prevState 上 [1] 的值才是之前的依赖值。var prevDeps = prevState[1];
// 判断以后的依赖的值和之前依赖的值是否相等
if (areHookInputsEqual(nextDeps, prevDeps)) {// prevState[0]就是之前的那个 callback,阐明函数没变,还是那个
return prevState[0];
}
}
}
// 这里是 prevState 不存在,或者 nextDeps(以后值)和 prevDeps(前值)不同
// 或者 nextDeps 不存在(等于是变动了,也就是说,如果第二个参数传入 null,每次都会从新定义函数)hook.memoizedState = [callback, nextDeps];
// 返回新函数
return callback;
}
附上 areHookInputsEqual 的源码:
function areHookInputsEqual(nextDeps, prevDeps) {
{if (ignorePreviousDependencies) {
// Only true when this component is being hot reloaded.
return false;
}
}
if (prevDeps === null) {
{error('%s received a final argument during this render, but not during' + 'the previous render. Even though the final argument is optional,' + 'its type cannot change between renders.', currentHookNameInDev);
}
return false;
}
{
// Don't bother comparing lengths in prod because these arrays should be
// passed inline.
if (nextDeps.length !== prevDeps.length) {error('The final argument passed to %s changed size between renders. The' + 'order and size of this array must remain constant.\n\n' + 'Previous: %s\n' + 'Incoming: %s', currentHookNameInDev, "[" + prevDeps.join(',') + "]", "[" + nextDeps.join(',') + "]");
}
}
// 只有这部分是重要的,这里是做了浅比拟。for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++) {if (objectIs(nextDeps[i], prevDeps[i])) {continue;}
return false;
}
return true;
}
正文完