React中useCallback useMemo使用方法快速精通
首先從簡單的講一下兩者的區(qū)別
useCallback和useMemo的區(qū)別
基本使用
// 貼上代碼片利于復(fù)制
import { React, useState, useMemo, useCallback } from "react";
export default function TestPage() {
const callBack = useCallback(() => {
console.log(1);
}, []);
const memo = useMemo(() => 123, []);
console.log("callback", callBack);
console.log("memo是", memo);
return (
<div>
<div>一個(gè)專門用于vue測(cè)試的頁面</div>
</div>
);
}
控制臺(tái)輸出如下

可以直觀的看到,useCallBack返回的是一個(gè)函數(shù),useMemo返回的是一個(gè)變量。
接下來我們來剖析這兩個(gè)東西的用法
useMemo
首先從簡單的講起,如果你學(xué)過Vue的話,完全可以把它當(dāng)成Computed來理解。在這里舉一個(gè)很好理解的
import { React, useState, useMemo, useCallback } from "react";
export default function TestPage() {
const [data, updateData] = useState(1);
const getComplicatedValue = () => {
console.log("開始計(jì)算一個(gè)復(fù)雜的value值啦!");
let total = 0;
for (let i = 0; i < 100; i++) {
total += i;
}
return total;
};
const changeData = () => {
updateData((oldValue) => oldValue + 1);
};
return (
<div>
<div>一個(gè)專門用于vue測(cè)試的頁面</div>
<div>這是一個(gè)復(fù)雜函數(shù)計(jì)算出來的值{getComplicatedValue()}</div>
<div>這是一個(gè)簡簡單單的data值{data}</div>
<button onClick={changeData}>點(diǎn)擊我改變data值</button>
</div>
);
}
大意就是,頁面上有一個(gè)很簡單的值data,還有一個(gè)很復(fù)雜的經(jīng)過函數(shù)計(jì)算出來的值getComplicatedValue,這里我用從1加到100來模擬了一個(gè)很復(fù)雜的計(jì)算過程(實(shí)際項(xiàng)目會(huì)更復(fù)雜)。
頁面顯示如下

顯示正常,根據(jù)控制臺(tái)顯示也可以看到getComplicatedValue函數(shù)也被正常調(diào)用了。接下來我們點(diǎn)擊按鈕改變data的值。

可以看到頁面是正常更新了的,但是性能問題出現(xiàn)了,我改變了data的值,導(dǎo)致render函數(shù)重新執(zhí)行,然后getComplicatedValue又被執(zhí)行了一遍!也就是計(jì)算機(jī)重新計(jì)算了1加到100。那么問題出現(xiàn)了,如果我是1加到100000呢?很顯然,在我們更新data值的時(shí)候,并不需要getComplicatedValue再次執(zhí)行,而是希望它的計(jì)算值被緩存起來。useMemo閃亮登場(chǎng)!!!當(dāng)當(dāng)當(dāng)當(dāng)。
改寫如下,改寫只需要改動(dòng)兩行
import { React, useState, useMemo, useCallback } from "react";
export default function TestPage() {
const [data, updateData] = useState(1);
const getComplicatedValue = useMemo(() => {
console.log("開始計(jì)算一個(gè)復(fù)雜的value值啦!");
let total = 0;
for (let i = 0; i < 100; i++) {
total += i;
}
return total;
},[]);
const changeData = () => {
updateData((oldValue) => oldValue + 1);
};
return (
<div>
<div>一個(gè)專門用于vue測(cè)試的頁面</div>
<div>這是一個(gè)復(fù)雜函數(shù)計(jì)算出來的值{getComplicatedValue}</div>
<div>這是一個(gè)簡簡單單的data值{data}</div>
<button onClick={changeData}>點(diǎn)擊我改變data值</button>
</div>
);
}
第四行把getComplicatedValue函數(shù)用useMemo包裹起來。第18行刪除(),因?yàn)閯倓傄呀?jīng)說過,useMemo返回的是一個(gè)值而不是函數(shù)。
接下來再看看頁面效果

這次可以看到,無論data值更新多少次,getComplicatedValue永遠(yuǎn)只執(zhí)行了初始化的那一次。
來個(gè)首尾呼應(yīng)
基本使用
const memo = useMemo(() => {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->},[依賴項(xiàng)數(shù)組])如果依賴項(xiàng)數(shù)組里面的數(shù)據(jù)沒有變化,那么memo值永遠(yuǎn)使用緩存,而不會(huì)重新計(jì)算
useCallback
useCallback比起useMemo就難上了一丟丟,因?yàn)樯婕暗搅俗咏M件。當(dāng)然也是灰常簡單。
首先來看一個(gè)簡單
父組件
import { React, useState, useMemo, useCallback } from "react";
import TestSonComp from "./testSonComp";
export default function TestPage() {
const [data, updateData] = useState(1);
const getValue = () => {
console.log("我是父組件的一個(gè)函數(shù)");
};
const changeData = () => {
updateData((oldValue) => oldValue + 1);
};
return (
<div>
<div>一個(gè)專門用于vue測(cè)試的頁面</div>
<div>這是一個(gè)簡簡單單的data值{data}</div>
<button onClick={changeData}>點(diǎn)擊我改變data值</button>
<TestSonComp getValue={getValue} />
</div>
);
}
子組件
import { React, memo } from "react";
const TestSonComp = (props) => {
console.log("子組件render函數(shù)執(zhí)行了");
return <div>一個(gè)子組件</div>;
};
export default TestSonComp;

頁面顯示正常,然后點(diǎn)擊按鈕更新數(shù)據(jù)

那么此時(shí)問題又出現(xiàn)了,我就是在父組件中改了一下data值,data值導(dǎo)致父組件render重新執(zhí)行,render生成了一個(gè)新的getValue函數(shù),然后子組件props更新,導(dǎo)致子組件更新。那么有沒有一個(gè)方法可以把函數(shù)緩存起來呢?
useCallback閃亮登場(chǎng)。
直接改寫父組件定義函數(shù)的一行
const getValue = useCallback(() => {
console.log("我是父組件的一個(gè)函數(shù)");
}, []);
改完之后看頁面效果你依然會(huì)發(fā)現(xiàn)和上圖一樣,子組件依然會(huì)更新!
問題出在這
useCallback必須配合React.memo來使用
react的Hooks組件對(duì)props的淺比較是在memo里面比較的(類組件是在shouldComponentUpdate里面),如果沒有memo,那么你使用useCallback就沒有意義
怎么使用?
子組件直接改寫最后一行
export default memo(TestSonComp);
二話不說看效果

改寫成功
再來個(gè)溫故知新
基本使用
const callback = useCallback(() => {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->},[依賴項(xiàng)數(shù)組])如果依賴項(xiàng)數(shù)組里面的數(shù)據(jù)沒有變化,那么函數(shù)值也永遠(yuǎn)使用緩存。
到此這篇關(guān)于React中useCallback useMemo使用方法快速精通的文章就介紹到這了,更多相關(guān)React useCallback useMemo內(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及useContext詳解
- 解析React中useMemo與useCallback的區(qū)別
- react性能優(yōu)化useMemo與useCallback使用對(duì)比詳解
- React?正確使用useCallback?useMemo的方式
- React中useMemo、useCallback的具體使用
相關(guān)文章
React中常見的動(dòng)畫實(shí)現(xiàn)的幾種方式
本篇文章主要介紹了React中常見的動(dòng)畫實(shí)現(xiàn)的幾種方式,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-01-01
如何解決React useEffect鉤子帶來的無限循環(huán)問題
本文主要介紹了解決React useEffect鉤子帶來的無限循環(huán)問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
react-native使用react-navigation進(jìn)行頁面跳轉(zhuǎn)導(dǎo)航的示例
本篇文章主要介紹了react-native使用react-navigation進(jìn)行頁面跳轉(zhuǎn)導(dǎo)航的示例,具有一定的參考價(jià)值,有興趣的可以了解一下2017-09-09
使用 React 和 Threejs 創(chuàng)建一個(gè)VR全景項(xiàng)目的過程詳解
這篇文章主要介紹了使用 React 和 Threejs 創(chuàng)建一個(gè)VR全景項(xiàng)目的過程詳解,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04
React.memo 和 useMemo 的使用問題小結(jié)
隨著代碼的增加,每次的狀態(tài)改變,頁面進(jìn)行一次 reRender ,這將產(chǎn)生很多不必要的 reRender 不僅浪費(fèi)性能,從而導(dǎo)致頁面卡頓,這篇文章主要介紹了React.memo 和 useMemo 的使用問題小結(jié),需要的朋友可以參考下2022-11-11

