useCallback、useMemo、useContext 的使用与不使用对比
作用:缓存函数引用,防止每次渲染时创建新的函数实例,避免子组件不必要的重渲染。
点击后父组件重新渲染,观察下方两个子组件的渲染次数变化
不使用useCallback
渲染次数: 0
按钮点击次数: 0
使用useCallback
渲染次数: 0
按钮点击次数: 0
⚠️ 说明:左侧组件每次父组件更新都会重新渲染(因为函数引用改变), 右侧组件只在必要时重新渲染(函数引用保持不变)
作用:缓存计算结果,只在依赖项改变时重新计算,避免昂贵的重复计算。
点击后父组件重新渲染,但计算输入值没变,观察是否重新计算
不使用 useMemo
计算结果: 加载中...
计算耗时: -
(每次都重新计算)
使用 useMemo
计算结果: 加载中...
计算耗时: -
(依赖项未变时返回缓存值,耗时为上次计算的时间)
⚠️ 说明:左侧组件每次渲染都会重新计算(即使输入没变), 右侧组件只在输入改变时才重新计算。点击“父组件更新计数”按钮查看差异!
作用:跨组件层级传递数据,避免props层层传递(prop drilling)。
顶层组件(提供Context)
当前主题: dark
中间组件(不需要主题数据)
深层子组件 - 当前主题: dark
⚠️ 说明:深层子组件可以直接访问顶层的主题数据和方法, 无需通过中间组件层层传递props。点击“切换主题”按钮体验!
// 不使用 Context - 需要层层传递 props
<TopComponent theme={theme} onToggle={toggle}>
<MiddleComponent theme={theme} onToggle={toggle}>
<DeepChild theme={theme} onToggle={toggle} />
</MiddleComponent>
</TopComponent>
// 使用 Context - 直接在需要的地方获取
<ThemeContext.Provider value={{theme, toggle}}>
<TopComponent>
<MiddleComponent>
<DeepChild /> {/* 直接使用 useContext */}
</MiddleComponent>
</TopComponent>
</ThemeContext.Provider>• useCallback: 缓存函数,优化子组件渲染性能
• useMemo: 缓存计算结果,避免昂贵的重复计算
• useContext: 跨组件传递数据,简化组件间通信