useMemo和useCallback的使用

useMemo

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

把“創(chuàng)建”函數(shù)和依賴項(xiàng)數(shù)組作為參數(shù)傳入 useMemo,它僅會(huì)在某個(gè)依賴項(xiàng)改變時(shí)才重新計(jì)算 memoized 值。這種優(yōu)化有助于避免在每次渲染時(shí)都進(jìn)行高開銷的計(jì)算泽示。

也就是說useMemo可以讓函數(shù)在某個(gè)依賴項(xiàng)改變的時(shí)候才運(yùn)行铐刘,這可以避免很多不必要的開銷焊切。舉個(gè)例子:

不使用useMemo
function Example() {
    const [count, setCount] = useState(1);
    const [val, setValue] = useState('');
 
    function getNum() {
        return Array.from({length: count * 100}, (v, i) => i).reduce((a, b) => a+b)
    }
 
    return <div>
        <h4>總和:{getNum()}</h4>
        <div>
            <button onClick={() => setCount(count + 1)}>+1</button>
            <input value={val} onChange={event => setValue(event.target.value)}/>
        </div>
    </div>;
}

上面這個(gè)組件祸轮,維護(hù)了兩個(gè)state,可以看到getNum的計(jì)算僅僅跟count有關(guān)哀峻,但是現(xiàn)在無論是count還是val變化涡相,都會(huì)導(dǎo)致getNum重新計(jì)算,所以這里我們希望val修改的時(shí)候剩蟀,不需要再次計(jì)算催蝗,這種情況下我們可以使用useMemo

使用useMemo
function Example() {
    const [count, setCount] = useState(1);
    const [val, setValue] = useState('');
 
    const getNum = useMemo(() => {
        return Array.from({length: count * 100}, (v, i) => i).reduce((a, b) => a+b)
    }, [count])
 
    return <div>
        <h4>總和:{getNum}</h4>
        <div>
            <button onClick={() => setCount(count + 1)}>+1</button>
            <input value={val} onChange={event => setValue(event.target.value)}/>
        </div>
    </div>;
}

使用useMemo后育特,并將count作為依賴值傳遞進(jìn)去丙号,此時(shí)僅當(dāng)count變化時(shí)才會(huì)重新執(zhí)行getNum

useCallback

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

把內(nèi)聯(lián)回調(diào)函數(shù)及依賴項(xiàng)數(shù)組作為參數(shù)傳入 useCallback且预,它將返回該回調(diào)函數(shù)的 memoized 版本槽袄,該回調(diào)函數(shù)僅在某個(gè)依賴項(xiàng)改變時(shí)才會(huì)更新。當(dāng)你把回調(diào)函數(shù)傳遞給經(jīng)過優(yōu)化的并使用引用相等性去避免非必要渲染(例如 shouldComponentUpdate)的子組件時(shí)锋谐,它將非常有用遍尺。

看起來似乎和useMemo差不多,我們來看看這兩者有什么異同:

useMemouseCallback接收的參數(shù)都是一樣涮拗,都是在其依賴項(xiàng)發(fā)生變化后才執(zhí)行乾戏,都是返回緩存的值,區(qū)別在于useMemo返回的是函數(shù)運(yùn)行的結(jié)果三热,useCallback返回的是函數(shù)鼓择。

useCallback(fn, deps) 相當(dāng)于 useMemo(() => fn, deps)

使用場景

正如上面所說的,當(dāng)你把回調(diào)函數(shù)傳遞給經(jīng)過優(yōu)化的并使用引用相等性去避免非必要渲染(例如 shouldComponentUpdate)的子組件時(shí)就漾,它將非常有用呐能。也就是說父組件傳遞一個(gè)函數(shù)給子組件的時(shí)候,由于父組件的更新會(huì)導(dǎo)致該函數(shù)重新生成從而傳遞給子組件的函數(shù)引用發(fā)生了變化抑堡,這就會(huì)導(dǎo)致子組件也會(huì)更新摆出,而很多時(shí)候子組件的更新是沒必要的,所以我們可以通過useCallback來緩存該函數(shù)首妖,然后傳遞給子組件偎漫。舉個(gè)例子:

function Parent() {
    const [count, setCount] = useState(1);
    const [val, setValue] = useState('');
 
    const getNum = useCallback(() => {
        return Array.from({length: count * 100}, (v, i) => i).reduce((a, b) => a+b)
    }, [count])
 
    return <div>
        <Child getNum={getNum} />
        <div>
            <button onClick={() => setCount(count + 1)}>+1</button>
            <input value={val} onChange={event => setValue(event.target.value)}/>
        </div>
    </div>;
}

const Child = React.memo(function ({ getNum }: any) {
    return <h4>總和:{getNum()}</h4>
})

使用useCallback之后,僅當(dāng)count發(fā)生變化時(shí)Child組件才會(huì)重新渲染有缆,而val變化時(shí)象踊,Child組件是不會(huì)重新渲染的温亲。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市杯矩,隨后出現(xiàn)的幾起案子栈虚,更是在濱河造成了極大的恐慌,老刑警劉巖菊碟,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件节芥,死亡現(xiàn)場離奇詭異,居然都是意外死亡逆害,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進(jìn)店門蚣驼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來魄幕,“玉大人,你說我怎么就攤上這事颖杏〈吭桑” “怎么了?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵留储,是天一觀的道長翼抠。 經(jīng)常有香客問我,道長获讳,這世上最難降的妖魔是什么阴颖? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮丐膝,結(jié)果婚禮上量愧,老公的妹妹穿的比我還像新娘。我一直安慰自己帅矗,他們只是感情好偎肃,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著浑此,像睡著了一般累颂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凛俱,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天紊馏,我揣著相機(jī)與錄音,去河邊找鬼最冰。 笑死瘦棋,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的暖哨。 我是一名探鬼主播赌朋,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼凰狞,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了沛慢?” 一聲冷哼從身側(cè)響起赡若,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎团甲,沒想到半個(gè)月后逾冬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡躺苦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年身腻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片匹厘。...
    茶點(diǎn)故事閱讀 40,498評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嘀趟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出愈诚,到底是詐尸還是另有隱情她按,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布炕柔,位于F島的核電站酌泰,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏匕累。R本人自食惡果不足惜陵刹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望哩罪。 院中可真熱鬧授霸,春花似錦、人聲如沸际插。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽框弛。三九已至辛辨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瑟枫,已是汗流浹背斗搞。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留慷妙,地道東北人僻焚。 一個(gè)月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像膝擂,于是被迫代替她去往敵國和親虑啤。 傳聞我的和親對象是個(gè)殘疾皇子隙弛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內(nèi)容