React中useMemo、useCallback的具體使用
useMemo
useMemo
用于 緩存 計(jì)算結(jié)果,避免不必要的重新計(jì)算。它返回一個(gè)記憶化的值,僅在 依賴項(xiàng)變化時(shí)重新計(jì)算,否則會(huì)返回上次計(jì)算的結(jié)果。這樣可以有效減少昂貴的計(jì)算或渲染。
語(yǔ)法:
let xxx = useMemo(callback,[dependencies])
- 第一次渲染組件的時(shí)候,
callback會(huì)執(zhí)行 - 后期只有依賴的狀態(tài)值發(fā)生改變,
callback才會(huì)再執(zhí)行 - 每一次會(huì)把callback執(zhí)行的返回結(jié)果賦值給xxx
useMemo具備“計(jì)算緩存”,在依賴的狀態(tài)值沒(méi)有發(fā)生改變,callback沒(méi)有觸發(fā)執(zhí)行的時(shí)候,xxx獲取的是上一次計(jì)算出來(lái)的結(jié)果- 和Vue中的計(jì)算屬性非常的類似!!
使用
const Demo = function Demo() {
console.log("渲染")
let [supNum, setSupNum] = useState(10),
[oppNum, setOppNum] = useState(5),
[x, setX] = useState(0);
let ratio = useMemo(() => {
console.log(useMemo,'useMemo')
let total = supNum + oppNum,
ratio = '--';
if (total > 0) ratio = (supNum / total * 100).toFixed(2) + '%';
return ratio;
}, [supNum, oppNum]);
return <div className="vote-box">
<div className="main">
<p>支持人數(shù):{supNum}人</p>
<p>反對(duì)人數(shù):{oppNum}人</p>
<p>支持比率:{ratio}</p>
<p>x:{x}</p>
</div>
<div className="footer">
<Button type="primary" onClick={() => setSupNum(supNum + 1)}>支持</Button>
<Button type="primary" danger onClick={() => setOppNum(oppNum + 1)}>反對(duì)</Button>
<Button onClick={() => setX(x + 1)}>干點(diǎn)別的事</Button>
</div>
</div>;
};
初始渲染,打印如下:

點(diǎn)擊新增,打印如下:

點(diǎn)擊干點(diǎn)別的事,打印如下:

注意事項(xiàng)
useMemo 不會(huì)提高性能的使用頻率,它只是優(yōu)化那些需要高開(kāi)銷計(jì)算的場(chǎng)景。如果計(jì)算本身就很輕量化,使用 useMemo 反而可能帶來(lái)額外的性能開(kāi)銷。
useMemo 不會(huì)阻止組件重新渲染,它只是在渲染過(guò)程中緩存某些計(jì)算值。
useCallback
useCallback 用于 緩存函數(shù),避免函數(shù)在每次渲染時(shí)都被重新創(chuàng)建。它返回一個(gè)記憶化的回調(diào)函數(shù),只有當(dāng)依賴項(xiàng)變化時(shí),才會(huì)重新創(chuàng)建該函數(shù)。雖然減少了堆內(nèi)存的開(kāi)辟,但是useCallback本身也有自己的處理邏輯和緩存機(jī)制,這個(gè)也消耗時(shí)間。
語(yǔ)法
const xxx = useCallback(callback,[dependencies])
- 組件第一次渲染,
useCallback執(zhí)行,創(chuàng)建一個(gè)函數(shù)“callback”,賦值給xxx - 組件后續(xù)每一次更新,判斷依賴的狀態(tài)值是否改變,如果改變,則重新創(chuàng)建新的函數(shù)堆,賦值給
xxx;但是如果,依賴的狀態(tài)沒(méi)有更新「或者沒(méi)有設(shè)置依賴“[]”」則xxx獲取的一直是第一次創(chuàng)建的函數(shù)堆,不會(huì)創(chuàng)建新的函數(shù)出來(lái)??! - 或者說(shuō),基于
useCallback,可以始終獲取第一次創(chuàng)建函數(shù)的堆內(nèi)存地址(或者說(shuō)函數(shù)的引用)
適用場(chǎng)景
useCallback主要用于優(yōu)化傳遞給子組件的函數(shù),避免每次父組件重新渲染時(shí),子組件因?yàn)榻邮艿叫碌暮瘮?shù)引用而重新渲染。
父組件更新時(shí),傳遞給子組件的屬性僅僅是一個(gè)函數(shù)「特點(diǎn):基本應(yīng)該算不變的」,不再讓子組件也跟著更新。
1、傳遞給子組件的屬性(函數(shù)),每一次需要是相同的堆內(nèi)存地址(是一致的),基于useCallback處理。
2、在子組件內(nèi)部也要做一個(gè)處理,驗(yàn)證父組件傳遞的屬性是否發(fā)生改變,如果沒(méi)有變化,則讓子組件不能更新,有變化才需要更新。子組件需要判斷傳遞過(guò)來(lái)的屬性有沒(méi)有變化,此時(shí)
- 類組件可以使用
React.PureComponent即可「在shouldComponentUpdate中對(duì)新老屬性做了淺比較」 - 函數(shù)組件可以使用
React.memo函數(shù),對(duì)新老傳遞的屬性做比較,如果不一致,才會(huì)把函數(shù)組件執(zhí)行,如果一致,則不讓子組件更新。
使用
父組件
const Demo = function Demo() {
let [x, setX] = useState(0);
// const handle = () => { }; //第一次:0x001 第二次:0x101 第三次:0x201 ...
const handle = useCallback(() => { }, []); //第一次:0x001 第二次:0x001 第三次:0x001 ...
return <div className="vote-box">
<Child handle={handle} />
<div className="main">
<p>{x}</p>
</div>
<div className="footer">
<Button type="primary" onClick={() => setX(x + 1)}>累加</Button>
</div>
</div>;
};
子組件為類組件
class Child extends React.PureComponent {
render() {
console.log('Child Render');
return <div>
我是子組件
</div>;
}
}
子組件為函數(shù)組件
const Child = React.memo(function Child(props) {
console.log('Child Render');
return <div>
我是子組件
</div>;
});
useCallback 對(duì)性能的優(yōu)化主要體現(xiàn)在避免子組件不必要的重新渲染,尤其是在子組件是 React.memo 或 shouldComponentUpdate 進(jìn)行優(yōu)化時(shí)。
到此這篇關(guān)于React中useMemo、useCallback的具體使用的文章就介紹到這了,更多相關(guān)React useMemo useCallback內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- React Hooks之使用useCallback和useMemo進(jìn)行性能優(yōu)化方式
- 詳解React中的useMemo和useCallback的區(qū)別
- 深入React?18源碼useMemo?useCallback?memo用法及區(qū)別分析
- React中memo useCallback useMemo方法作用及使用場(chǎng)景
- React中useCallback useMemo使用方法快速精通
- React中useCallback useMemo到底該怎么用
- React源碼分析之useCallback與useMemo及useContext詳解
- 解析React中useMemo與useCallback的區(qū)別
- react性能優(yōu)化useMemo與useCallback使用對(duì)比詳解
- React?正確使用useCallback?useMemo的方式
相關(guān)文章
ReactNative實(shí)現(xiàn)弧形拖動(dòng)條的代碼案例
本文介紹了ReactNative實(shí)現(xiàn)弧形拖動(dòng)條,本組件使用到了react-native-svg和PanResponder,結(jié)合示例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-02-02
React如何使用localStorage及實(shí)現(xiàn)刪除筆記操作過(guò)程
這篇文章主要介紹了React如何使用localStorage及實(shí)現(xiàn)刪除筆記操作過(guò)程,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2024-12-12
React?Fiber構(gòu)建completeWork源碼解析
這篇文章主要為大家介紹了React?Fiber構(gòu)建completeWork源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
一百多行代碼實(shí)現(xiàn)react拖拽hooks
這篇文章主要介紹了一百多行代碼實(shí)現(xiàn)react拖拽hooks,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03

