TL;博士
有的博客说不需要useCallback
每次给子组件传递回调时都使用钩子,有时每次都创建一个新函数会更好。因为useCallback
有时成本高于实际性能问题。虽然 React 警告说它可能会导致性能问题,但我们需要尽量避免它。
谁是对的,在这两种对立的主张之间取得平衡的方法是什么?
完整的问题
我最近一直在阅读很多关于 React hooks 的博客和教程,特别是关于useCallback
和useMemo
.
在 React 16(及其所有钩子)之前,当我使用类组件时,我一直使用“构造函数绑定”进行回调,因为箭头函数或“渲染中的绑定”如下所示:
render() {
return <button onClick={this.handleClick.bind(this)}>Click Me</button>;
}
render() {
return <button onClick={() => this.handleClick()}>Click Me</button>;
}
被认为是“不良做法”。来自React 文档:
在渲染中使用 Function.prototype.bind 会在每次渲染组件时创建一个新函数,这可能会影响性能(见下文)。
在渲染中使用箭头函数会在每次渲染组件时创建一个新函数,这可能会破坏基于严格标识比较的优化。
所以,我的经验法则是不要将新函数传递给 props。
在 React 16 中,useCallback
钩子试图帮助我们做那件事。但是我看到很多类似的博客声称您不需要每次都使用钩子,因为有时成本高于实际问题,并且使用箭头函数在每次渲染时创建一个新函数很好。useCallback
useCallback
两种相反的说法都让我认为最好的选择应该是这样的(如果依赖项数组为空):
function handleCallback() { ... } // Or arrow function...
function Foo(props) {
return <button onClick={handleCallback}>Click Me</button>
}
因为这种方式不使用“昂贵” useCallback
,并且不会每次都生成新功能。但是,实际上,当您有多个回调时,这段代码看起来并不那么好。
那么,这两种对立的主张之间的正确平衡是什么?如果每次创建一个新函数有时比使用更好useCallback
,为什么 React 在他们的文档中有一个警告?
(关于“双花括号”经验法则和useMemo
/useRef
钩子的相同问题)