问题描述
如docs 中所述,useCallback
返回一个记忆回调.
As said in docs, useCallback
Returns a memoized callback.
传递内联回调和输入数组.useCallback
将返回回调的记忆版本,该版本仅在输入之一发生更改时才会更改.这在将回调传递给依赖引用相等性的优化子组件时很有用,以防止不必要的渲染(例如 shouldComponentUpdate).
Pass an inline callback and an array of inputs. useCallback
will return a memoized version of the callback that only changes if one of the inputs has changed. This is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders (e.g. shouldComponentUpdate).
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
但是它是如何工作的以及在 React 中使用它的最佳位置是什么?
But how does it work and where is the best to use it in React?
附言我认为使用 codepen 示例 进行可视化将有助于每个人更好地理解它.在文档中解释.
P.S. I think visualisation with codepen example will help everyone to understand it better. Explained in docs.
推荐答案
当您想防止不必要的重新渲染以获得更好的性能时,最好使用此方法.
This is best used when you want to prevent unnecessary re-renders for better performance.
比较这两种将回调传递给从 React 文档:
Compare these two ways of passing callbacks to child components taken from React Docs:
class Foo extends Component {
handleClick() {
console.log('Click happened');
}
render() {
return <Button onClick={() => this.handleClick()}>Click Me</Button>;
}
}
2.在构造函数中绑定(ES2015)
class Foo extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log('Click happened');
}
render() {
return <Button onClick={this.handleClick}>Click Me</Button>;
}
}
假设 被实现为
PureComponent
,第一种方式会导致 每次重新渲染
重新渲染,因为在每个
render()
调用中都会创建一个新函数.在第二种方式中,handleClick
方法只在 的构造函数中创建一次,并在渲染中重复使用.
Assuming <Button>
is implemented as a PureComponent
, the first way will cause <Button>
to re-render every time <Foo>
re-renders because a new function is created in every render()
call. In the second way, the handleClick
method is only created once in <Foo>
's constructor and reused across renders.
如果我们使用钩子将这两种方法转换为函数式组件,则它们是等效的(有点):
If we translate both approaches to functional components using hooks, these are the equivalents (sort of):
function Foo() {
const handleClick = () => {
console.log('Click happened');
}
return <Button onClick={handleClick}>Click Me</Button>;
}
2.在构造函数中绑定(ES2015)->记忆回调
function Foo() {
const memoizedHandleClick = useCallback(
() => console.log('Click happened'), [],
); // Tells React to memoize regardless of arguments.
return <Button onClick={memoizedHandleClick}>Click Me</Button>;
}
第一种方式在函数组件的每次调用时都会创建回调,但第二种方式,React 会为您记忆回调函数,并且不会多次创建回调.
The first way creates callbacks on every call of the functional component but in the second way, React memoizes the callback function for you and the callback is not created multiple times.
因此在第一种情况下,如果 Button
是使用 React.memo
实现的,它将始终重新呈现(除非您有一些自定义比较函数),因为 onClick
prop 每次都不同,在第二种情况下,它不会.
Hence in the first case if Button
is implemented using React.memo
it will always re render (unless you have some custom comparison function) because the onClick
prop is different each time, in the second case, it won't.
在大多数情况下,采用第一种方式没问题.正如 React 文档所述:
In most cases, it's fine to do the first way. As the React docs state:
在渲染方法中使用箭头函数可以吗?通常来说,一般来说,是的,没关系,而且通常是将参数传递给的最简单方法回调函数.
如果您确实有性能问题,请务必进行优化!
If you do have performance issues, by all means, optimize!
这篇关于在 React 中 useCallback/useMemo 有什么作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!