React Hooks: useCallback理解
<h2>useCallback把匿名回调“存”起来</h2><p>避免在component render时候声明匿名方法,因为这些匿名方法会被反复重新声明而无法被多次利用,然后容易造成component反复不必要的渲染。</p>
<p> 在Class component当中我们通常将回调函数声明为类成员:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">class MyComponent extends React.Component {
constructor(props) {
super(props);
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.clickCallback = <span style="color: rgba(0, 0, 255, 1)">this</span>.clickCallback.bind(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">);
}
clickCallback() {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ...</span>
<span style="color: rgba(0, 0, 0, 1)"> }
render() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <button onClick={<span style="color: rgba(0, 0, 255, 1)">this</span>.clickCallback}>Click Me!</button>;
<span style="color: rgba(0, 0, 0, 1)"> }
}</span></pre>
</div>
<p>使用useCallback hook就可以避免bind操作:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> MyComponent(props) {
const clickCallback </span>= React.useCallback(() =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ...</span>
<span style="color: rgba(0, 0, 0, 1)"> }, []);
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <button onClick={clickCallback}>Click Me!</button>;
}</pre>
</div>
<h2>useCallback缓存函数</h2>
<div class="cnblogs_Highlighter">
<pre class="brush:javascript;gutter:true;">const fnA = useCallback(fnB, )
</pre>
</div>
<p> 上面的useCallback会将我们传递给它的函数fnB返回,并且将这个结果缓存;当依赖a变更时,会返回新的函数。既然返回的是函数,我们无法很好的判断返回的函数是否变更,所以我们可以借助ES6新增的数据类型Set来判断,具体如下:</p>
<div class="cnblogs_code">
<pre>import React, { useState, useCallback } from 'react'<span style="color: rgba(0, 0, 0, 1)">;
const set </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Set();
export </span><span style="color: rgba(0, 0, 255, 1)">default</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> Callback() {
const </span>= useState(1<span style="color: rgba(0, 0, 0, 1)">);
const </span>= useState(''<span style="color: rgba(0, 0, 0, 1)">);
const callback </span>= useCallback(() =><span style="color: rgba(0, 0, 0, 1)"> {
console.log(count);
}, );
set.add(callback);
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <div>
<h4>{count}</h4>
<h4>{set.size}</h4>
<div>
<button onClick={() => setCount(count + 1)}>+</button>
<input value={val} onChange={event => setVal(event.target.value)}/>
</div>
</div>;
}</pre>
</div>
<p>我们可以看到,每次修改count,set.size就会+1,这说明useCallback依赖变量count,count变更时会返回新的函数;而val变更时,set.size不会变,说明返回的是缓存的旧版本函数。</p>
<h2>使用场景:</h2>
<p>有一个父组件,其中包含子组件,子组件接收一个函数作为props;通常而言,如果父组件更新了,子组件也会执行更新;但是大多数场景下,更新是没有必要的,我们可以借助useCallback来返回函数,然后把这个函数作为props传递给子组件;这样,子组件就能避免不必要的更新。</p>
<div class="cnblogs_code">
<pre>import React, { useState, useCallback, useEffect } from 'react'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> Parent() {
const </span>= useState(1<span style="color: rgba(0, 0, 0, 1)">);
const </span>= useState(''<span style="color: rgba(0, 0, 0, 1)">);
const callback </span>= useCallback(() =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> count;
}, );
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <div>
<h4>{count}</h4>
<Child callback={callback}/>
<div>
<button onClick={() => setCount(count + 1)}>+</button>
<input value={val} onChange={event => setVal(event.target.value)}/>
</div>
</div>;
<span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> Child({ callback }) {
const </span>= useState(() =><span style="color: rgba(0, 0, 0, 1)"> callback());
useEffect(() </span>=><span style="color: rgba(0, 0, 0, 1)"> {
setCount(callback());
}, );
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <div><span style="color: rgba(0, 0, 0, 1)">
{count}
</span></div>
}</pre>
</div>
<p>不仅是上面的例子,所有依赖本地状态或props来创建函数,需要使用到缓存函数的地方,都是useCallback的应用场景。</p>
<p>useEffect、useMemo、useCallback都是自带闭包的。也就是说,每一次组件的渲染,其都会捕获当前组件函数上下文中的状态(state, props),所以每一次这三种hooks的执行,反映的也都是当前的状态,你无法使用它们来捕获上一次的状态。对于这种情况,我们应该使用ref来访问。</p><br><br>
来源:https://www.cnblogs.com/Nyan-Workflow-FC/p/11287276.html
頁:
[1]