避免在component render時候聲明匿名方法,由於這些匿名方法會被反覆從新聲明而沒法被屢次利用,而後容易形成component反覆沒必要要的渲染。javascript
在Class component當中咱們一般將回調函數聲明爲類成員:java
class MyComponent extends React.Component { constructor(props) { super(props); this.clickCallback = this.clickCallback.bind(this); } clickCallback() { // ... } render() { return <button onClick={this.clickCallback}>Click Me!</button>; } }
使用useCallback hook就能夠避免bind操做:react
function MyComponent(props) { const clickCallback = React.useCallback(() => { // ... }, []); return <button onClick={clickCallback}>Click Me!</button>; }
const fnA = useCallback(fnB, [a])
上面的useCallback會將咱們傳遞給它的函數fnB返回,而且將這個結果緩存;當依賴a變動時,會返回新的函數。既然返回的是函數,咱們沒法很好的判斷返回的函數是否變動,因此咱們能夠藉助ES6新增的數據類型Set來判斷,具體以下:緩存
import React, { useState, useCallback } from 'react'; const set = new Set(); export default function Callback() { const [count, setCount] = useState(1); const [val, setVal] = useState(''); const callback = useCallback(() => { console.log(count); }, [count]); set.add(callback); return <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>; }
咱們能夠看到,每次修改count,set.size就會+1,這說明useCallback依賴變量count,count變動時會返回新的函數;而val變動時,set.size不會變,說明返回的是緩存的舊版本函數。閉包
有一個父組件,其中包含子組件,子組件接收一個函數做爲props;一般而言,若是父組件更新了,子組件也會執行更新;可是大多數場景下,更新是沒有必要的,咱們能夠藉助useCallback來返回函數,而後把這個函數做爲props傳遞給子組件;這樣,子組件就能避免沒必要要的更新。函數
import React, { useState, useCallback, useEffect } from 'react'; function Parent() { const [count, setCount] = useState(1); const [val, setVal] = useState(''); const callback = useCallback(() => { return count; }, [count]); return <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>; } function Child({ callback }) { const [count, setCount] = useState(() => callback()); useEffect(() => { setCount(callback()); }, [callback]); return <div> {count} </div> }
不只是上面的例子,全部依賴本地狀態或props來建立函數,須要使用到緩存函數的地方,都是useCallback的應用場景。this
useEffect、useMemo、useCallback都是自帶閉包的。也就是說,每一次組件的渲染,其都會捕獲當前組件函數上下文中的狀態(state, props),因此每一次這三種hooks的執行,反映的也都是當前的狀態,你沒法使用它們來捕獲上一次的狀態。對於這種狀況,咱們應該使用ref來訪問。spa