Skip to content

useCallback

介绍

useCallback 是 React 提供的 Hook,用于缓存函数引用。当依赖项没有变化时,它会返回同一个函数实例,从而避免在子组件或副作用中因为“新函数”触发不必要的重新渲染或重复执行。

快速入门

语法

ts
const memoizedCallback = useCallback<T extends (...args: any[]) => any>(
	callback: T,
	dependencies: DependencyList,
)

参数说明:

  1. callback:需要被记忆化的函数。React 在依赖变化时返回一个新的函数引用。
  2. 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 重新渲染。

基于 MIT 许可发布