学习React-18-useCallBack
useCallback 简介
useCallback
是 React 中的一个 Hook,用于优化性能,避免在每次渲染时重新创建函数。它通过缓存函数实例,仅在依赖项变化时重新创建函数。适用于需要将函数作为 props 传递给子组件或依赖函数引用的场景。
基本语法
const memoizedCallback = useCallback(() => {// 函数逻辑},[dependencies] // 依赖项数组
);
参数
- callback 回调函数
- dependencies 依赖项,当依赖项发生变化时会调用回调函数
返回值
- 返回一个记忆化的回调函数,可以减少函数的创建次数,提高性能。
使用场景
避免不必要的子组件渲染
当父组件传递回调函数给子组件时,如果父组件重新渲染,子组件也会重新渲染(即使 props 未变化)。使用 useCallback
可以缓存函数,避免子组件不必要的渲染。
依赖函数引用的优化
在 useEffect
或其他 Hook 中,如果依赖项包含函数,使用 useCallback
可以避免因函数引用变化而触发不必要的副作用。
小栗子
import React, { useState, useCallback } from 'react'
// 创建WeakMap用于记录加载几次
const map = new WeakMap()
let renderCount = 1
export const TestCallBack: React.FC = () => {const [count, setCount] = useState('')const changeCount = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {setCount(e.target.value)}, [])if(!map.has(changeCount)) {map.set(changeCount, renderCount++)}console.log(`renderCount: ${map.get(changeCount)}`)return (<div><h3>测试UseTextCallBack</h3><input type="text" onChange={changeCount} /></div>)
}export default TestCallBack
效果演示:


中栗子
import React, { useState, useCallback, useMemo } from 'react'interface ChildData {btnName: stringbtnClick: () => void
}const Child: React.FC<ChildData> = React.memo((props) => {console.log('子组件渲染了')const { btnName, btnClick } = propsreturn (<div><button onClick={btnClick}>{btnName}</button></div>)
})export const TestCallBack: React.FC = () => {const [count, setCount] = useState('')// const btnClick = () => {// console.log('点击了')// }const btnClick = useCallback(() => {console.log('点击了')}, [])return (<div><h3>测试UseTextCallBack</h3><input value={count} onChange={(e) => setCount(e.target.value)} /><Child btnName="点击" btnClick={btnClick} /></div>)
}export default TestCallBack
效果如下:


这里可直观的看到在没有使用useCallBack之前,即使使用了useMemo,当输入框的state变化时,子组件还是重新渲染。所以这是为什么呢?原因很简单,在你每次输入的时候,浏览器都会将App重新渲染,所以参数的函数内存地址也会发生变化,这就导致浏览器认为这是一个新的,所以就重新渲染。
注意事项
-
依赖项数组
确保所有依赖项(如 state、props 或其他变量)都正确添加到依赖项数组中,否则可能导致闭包问题或过时的值。 -
过度优化的风险
并非所有函数都需要使用useCallback
。过度使用可能会增加代码复杂度,反而降低性能。仅在必要时使用。 -
与
React.memo
结合使用
useCallback
通常与React.memo
一起使用,避免子组件因函数引用变化而重新渲染。
性能对比
未使用 useCallback
时,每次父组件渲染都会创建新的函数实例,导致子组件重新渲染。使用后,函数实例被缓存,子组件仅在依赖项变化时重新渲染。
总结
useCallback
是 React 性能优化的重要工具,适用于需要缓存函数引用的场景。合理使用可以减少不必要的渲染,提升应用性能。
useCallback
并不是为了阻止函数的重新创建,而是通过依赖项来决定是否返回新的函数或旧的函数,从而在依赖项不变的情况下确保函数的地址不变。