useCallback 接受一个函数并返回它的 memoized 版本,也就是缓存该函数。

在 React 的函数式组件中,每次 UI 变化该函数就会重新执行。所以在函数式组件内部定义的函数是不会重复利用的,而是每次都会创建一个新的。创建一个新的函数后,在使用这个函数的组件也会接受一个新的函数,相当于接受的 props 更新了, 所以就需要重新渲染。

例如:

const AddButton = () => {
    const [count, setCount] = useState(0);
    const handleClick = () => setCount(count + 1);
    return <button onClick={handleClick}>{count}</button>
}

在 button 的 props 中我们传入了 handlkeClick,每次 UI 变化时 AddButton 这个组件就会重新执行一遍,然后重新创建一个 handleClick 函数,button 接受了新的 handleClick 函数就会重新渲染。

因此我们需要仅在 count 发生变化的时候才返回新的 handleClick 函数。这就是 useCallback 的作用。

useCallback 的函数签名如下:

useCallback(fn, deps)

fn 为我们定义的函数,deps 为依赖项数组,只有当这个数组中的变量变化了,fn 才会返回新的函数。依赖项数组类似于 useEffect

useCallback 其实并没有避免重复创建函数,因为在 useCallback(fn, [deps]) 的形式中,每次运行都会创建一个函数。useCallback 只是可以决定是不是要使用新的函数。在 依赖项不变的时候,就始终返回之前的,从而避免组件的重复渲染。

如果你确定组件重复渲染问题不大,那么 useCallback 用不用就问题不大。不过最佳实践是使用它处理内部定义的函数。