React useCallback使用教程
開(kāi)始之前請(qǐng)注意這句話:任何優(yōu)化都會(huì)增加復(fù)雜性,任何過(guò)早添加的優(yōu)化都會(huì)帶來(lái)風(fēng)險(xiǎn),因?yàn)閮?yōu)化后的代碼可能會(huì)多次更改
useEffect
相關(guān)作用:監(jiān)聽(tīng) & 初始化
//最簡(jiǎn)單用法
useEffect(() => {
//只有方法體,相當(dāng)于componentDidMount和componentDidUpdate中的代碼
document.title = count;
})
//加返回值用法
useEffect(() => {
//添加監(jiān)聽(tīng)事件,相當(dāng)于componentDidMount和componentDidUpdate中的代碼
window.addEventListener('resize', onChange, false);
//返回的函數(shù)用于解綁事件,相當(dāng)于componentWillUnmount中的代碼
return () => {
window.removeEventListener('resize', onChange, false)
}
})
//加空數(shù)組參數(shù)用法
useEffect(() => {
// 相當(dāng)于 componentDidMount
window.addEventListener('resize', onChange, false)
return () => {
// 相當(dāng)于 componentWillUnmount
window.removeEventListener('resize', onChange, false)
}
}, []);
//加監(jiān)聽(tīng)值用法
useEffect(() => {
//只有當(dāng)count的值發(fā)生變化,此函數(shù)才會(huì)執(zhí)行
console.log(`count change: count is ${count}`)
}, [ count ]);
useCallback
先看一個(gè)最簡(jiǎn)單的例子:
// 用于記錄 getData 調(diào)用次數(shù)
let count = 0;
function App() {
const [val, setVal] = useState("");
function getData() {
setTimeout(()=>{
setVal('new data '+count);
count++;
}, 500)
}
useEffect(()=>{
getData();
}, []);
return (
<div>{val}</div>
);}
getData模擬發(fā)起網(wǎng)絡(luò)請(qǐng)求。在這種場(chǎng)景下,沒(méi)有useCallback什么事,組件本身是高內(nèi)聚的。
如果涉及到組件通訊,情況就不一樣了:
// 用于記錄 getData 調(diào)用次數(shù)
let count = 0;
function App() {
const [val, setVal] = useState("");
function getData() {
setTimeout(() => {
setVal("new data " + count);
count++;
}, 500);
}
return <Child val={val} getData={getData} />;}function Child({val, getData}) {
useEffect(() => {
getData();
}, [getData]);
return <div>{val}</div>;}
就這么輕輕松松,一個(gè)死循環(huán)就誕生了…
先來(lái)分析下這段代碼的用意,Child組件是一個(gè)純展示型組件,其業(yè)務(wù)邏輯都是通過(guò)外部傳進(jìn)來(lái)的,這種場(chǎng)景在實(shí)際開(kāi)發(fā)中很常見(jiàn)。
再分析下代碼的執(zhí)行過(guò)程:
- App渲染Child,將val和getData傳進(jìn)去
- Child使用useEffect獲取數(shù)據(jù)。因?yàn)閷?duì)getData有依賴,于是將其加入依賴列表
- getData執(zhí)行時(shí),調(diào)用setVal,導(dǎo)致App重新渲染
- App重新渲染時(shí)生成新的getData方法,傳給Child
- Child發(fā)現(xiàn)getData的引用變了,又會(huì)執(zhí)行g(shù)etData
- 3 -> 5 是一個(gè)死循環(huán)
如果明確getData只會(huì)執(zhí)行一次,最簡(jiǎn)單的方式當(dāng)然是將其從依賴列表中刪除。但如果裝了 hook 的lint 插件,會(huì)提示:React Hook useEffect has a missing dependency
useEffect(() => {
getData();}, []);
實(shí)際情況很可能是當(dāng)getData改變的時(shí)候,是需要重新獲取數(shù)據(jù)的。這時(shí)就需要通過(guò)useCallback來(lái)將引用固定?。?/p>
const getData = useCallback(() => {
setTimeout(() => {
setVal("new data " + count);
count++;
}, 500);}, []);
上面例子中g(shù)etData的引用永遠(yuǎn)不會(huì)變,因?yàn)樗囊蕾嚵斜硎强铡?梢愿鶕?jù)實(shí)際情況將依賴加進(jìn)去,就能確保依賴不變的情況下,函數(shù)的引用保持不變。
還有一個(gè)要注意的是
在開(kāi)始監(jiān)聽(tīng)一個(gè)鼠標(biāo)的移動(dòng)的時(shí)候,想要?jiǎng)h除這個(gè)監(jiān)聽(tīng)不生效,由于是, 加入useState導(dǎo)致組件再次渲染 handleMouse 函數(shù)在次渲染, handleMouse 作為組件內(nèi)的方法, 會(huì)跟著一同再次渲染, 并且在內(nèi)存里, 再次渲染出的 clickFunc !== 前clickFunc.
所以removeEventListener無(wú)法解除綁定, 再次addEventListener則會(huì)綁定一個(gè)新方法.
document.addEventListener('mousemove',handleMouse,true)解決方案 : useCallback 緩存改方法 這時(shí)候的 document.removeEventListener(‘mousemove’,handleMouse,true) 中的handleMouse 和添加中的方法就是一個(gè)了,就能刪除了。
onst handleMouse= useCallback(() => {
//xxxx
console.log("clicking");
}, []);
到此這篇關(guān)于React useCallback使用教程的文章就介紹到這了,更多相關(guān)React useCallback內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
實(shí)現(xiàn)React單頁(yè)應(yīng)用的方法詳解
今天我們來(lái)學(xué)習(xí)React是如何構(gòu)建起一個(gè)單頁(yè)應(yīng)用的,React作為目前最流行的前端框架之一,其受歡迎程度不容小覷,從這門(mén)框架上我們可以學(xué)到許多其他前端框架所缺失的東西,也是其創(chuàng)新性所在的地方,比如虛擬DOM、JSX等。下面一起來(lái)看看。2016-08-08
React項(xiàng)目動(dòng)態(tài)設(shè)置title標(biāo)題的方法示例
這篇文章主要介紹了React項(xiàng)目動(dòng)態(tài)設(shè)置title標(biāo)題的方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-09-09
React Native 使用Fetch發(fā)送網(wǎng)絡(luò)請(qǐng)求的示例代碼
本篇文章主要介紹了React Native 使用Fetch發(fā)送網(wǎng)絡(luò)請(qǐng)求的示例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12
React學(xué)習(xí)之JSX與react事件實(shí)例分析
這篇文章主要介紹了React學(xué)習(xí)之JSX與react事件,結(jié)合實(shí)例形式分析了React中JSX表達(dá)式、屬性、嵌套與react事件相關(guān)使用技巧,需要的朋友可以參考下2020-01-01
在React項(xiàng)目中使用Eslint代碼檢查工具及常見(jiàn)問(wèn)題
這篇文章主要介紹了在React項(xiàng)目中使用Eslint代碼檢查工具及常見(jiàn)問(wèn)題,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-10-10
react項(xiàng)目打包后點(diǎn)擊index.html頁(yè)面出現(xiàn)空白的問(wèn)題
這篇文章主要介紹了react項(xiàng)目打包后點(diǎn)擊index.html頁(yè)面出現(xiàn)空白的問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06
在React項(xiàng)目中使用iframe嵌入一個(gè)網(wǎng)站的步驟
本文介紹了如何在React項(xiàng)目中通過(guò)iframe嵌入百度網(wǎng)站的步驟,首先創(chuàng)建一個(gè)Baidu.js組件,并在該組件中設(shè)置iframe來(lái)加載百度,然后在App.js中引入并使用Baidu組件,還討論了因安全策略可能無(wú)法加載某些網(wǎng)站的問(wèn)題,需要的朋友可以參考下2024-09-09

