第十三章:useCallback源码解析

前言

useCallbackuseMemo都是Hook中用于性能优化的;
useCallback 是一个允许你在多次渲染中缓存函数的 React Hook。

源码解析

js 复制代码
const cachedFn = useCallback(fn, dependencies)

mount阶段

按照常规流程,调用HooksDispatcherOnMountInDEV.useCallback 的方法,前置check检查方法,核心方法mountCallback

首先调用mountWorkInProgressHook方法,

js 复制代码
const hook = {
    memoizedState: null,
    baseState: null,
    baseQueue: null,
    queue: null,
    next: null
};
fiber.memoizedState = hook;

mountCallback核心代码就是将fn和dependencies保存下来,并返回fn;

js 复制代码
hook.memoizedState = [fn, dependencies];
return fn;

useCallback初始化阶段就是创建一个hook对象,然后将依赖和函数保存下来;

update阶段

调用HooksDispatcherOnUpdateInDEV.useCallback 方法,调用check方法,核心方法updateCallback

调用updateWorkInProgressHook 阶段,就是更新hook对象;

将hook.memoizedState获取的值和当前传入的值,Object.is(hook.memoizedState[1],dependencies),

如果是一样的,就返回hook.memoizedState[0],否则

js 复制代码
hook.memoizedState = [fn, dependencies];
return fn;

总结

useCallback源码很简单,就是将函数保存下来,根据前后两次dependencies,如果没变的话就是返回上次函数,否则就会返回当前函数。

补充

useCallback并不会导致组件更新,而用户直接使用useCallback减少不必要的函数创建,这并不是很好的优化方式,

我理解的有一种适合的场景,防止子组件的不必要渲染,如果将回调函数传递给 React.memo 包裹的子组件,使用 useCallback 可以确保即使父组件重新渲染,子组件也不会因为新的回调函数而重新渲染。

js 复制代码
const MemoizedChildComponent = React.memo(({ onClick }) => {
  // 子组件的渲染逻辑
  return <button onClick={onClick}>Click me</button>;
});

const ParentComponent = () => {
  const handleClick = useCallback(() => {
    console.log('Button clicked!');
  }, []);

  return <MemoizedChildComponent onClick={handleClick} />;
};

函数与依赖关系

无论是useCallback或者useEffect等有依赖项的hook,都是通过闭包实现的,举个简单例子

js 复制代码
// mount
let cache
function component(){
    let state = 'old' 
    function hook(){
        console.log(state)
    }
    cache = hook
    hook();
}
component()
// update

function component(){
    let state = 'new' 
    function hook(){
        console.log(state)
    }
    // if deps没变化 成立执行cache,否则执行hook
    cache()
}
component()

这就相当于使用useCallback的过程,第二次打印也是'old',

相关推荐
tedcloud1231 小时前
UI-TARS-desktop部署教程:构建AI桌面自动化系统
服务器·前端·人工智能·ui·自动化·github
UXbot4 小时前
AI原型设计工具如何支持团队协作与快速迭代
前端·交互·个人开发·ai编程·原型模式
ZC跨境爬虫5 小时前
跟着MDN学HTML_day_48:(Node接口)
前端·javascript·ui·html·音视频
红尘散仙6 小时前
一套 Rust 核心,跑通 Tauri + React Native
react native·react.js·rust
PieroPc6 小时前
CAMWATCH — 局域网摄像头监控系统 Fastapi + html
前端·python·html·fastapi·监控
巴巴博一7 小时前
2026 最新:Trae / Cursor 一键接入 taste-skill 完整教程(让 AI 前端告别“AI 味”)
前端·ai·ai编程
kyriewen8 小时前
半夜三点线上崩了,AI替我背了锅——用AI排错,五分钟定位三年老bug
前端·javascript·ai编程
kyriewen8 小时前
我让 AI 当了 24 小时全年无休的“毒舌考官”
前端·ci/cd·ai编程
hexu_blog8 小时前
vue+java实现图片批量压缩
java·前端·vue.js
IT_陈寒8 小时前
为什么你应该学习JavaScript?
前端·人工智能·后端