主题
useCallback
介绍
useCallback 是 React 提供的 Hook,用于缓存函数引用。当依赖项没有变化时,它会返回同一个函数实例,从而避免在子组件或副作用中因为“新函数”触发不必要的重新渲染或重复执行。
快速入门
语法
ts
const memoizedCallback = useCallback<T extends (...args: any[]) => any>(
callback: T,
dependencies: DependencyList,
)参数说明:
callback:需要被记忆化的函数。React 在依赖变化时返回一个新的函数引用。dependencies:依赖项数组,列出callback中用到的外部变量。
提示
useCallback 返回的是“稳定的函数引用”,它不会帮你执行函数或缓存结果;如果要缓存计算结果,请使用 useMemo。
示例
tsx
import { memo, useCallback, useState } from 'react'
const TodoItem = memo(function TodoItem({
id,
title,
onDelete,
}: {
id: number
title: string
onDelete: (id: number) => void
}) {
console.log('🔁 渲染 TodoItem:', title)
return (
<li style={{ display: 'flex', justifyContent: 'space-between', gap: 8 }}>
<span>{title}</span>
<button type="button" onClick={() => onDelete(id)}>
删除
</button>
</li>
)
})
function TodoList() {
const [todos, setTodos] = useState([
{ id: 1, title: '阅读 React 官方文档' },
{ id: 2, title: '完成组件单元测试' },
])
const handleDelete = useCallback((id: number) => {
setTodos((prev) => prev.filter((item) => item.id !== id))
}, [])
return (
<section style={{ maxWidth: 360 }}>
<h2>待办列表</h2>
<ul style={{ paddingLeft: 20, display: 'grid', gap: 8 }}>
{todos.map((todo) => (
<TodoItem key={todo.id} {...todo} onDelete={handleDelete} />
))}
</ul>
</section>
)
}
export default TodoList在上述示例中,如果不用 useCallback,父组件每次渲染都会生成新的 handleDelete,即使 todos 没变也会让 TodoItem 重新渲染。
