React useCallback使用教程
開始之前請(qǐng)注意這句話:任何優(yōu)化都會(huì)增加復(fù)雜性,任何過早添加的優(yōu)化都會(huì)帶來風(fēng)險(xiǎn),因?yàn)閮?yōu)化后的代碼可能會(huì)多次更改
useEffect
相關(guān)作用:監(jiān)聽 & 初始化
//最簡單用法 useEffect(() => { //只有方法體,相當(dāng)于componentDidMount和componentDidUpdate中的代碼 document.title = count; }) //加返回值用法 useEffect(() => { //添加監(jiān)聽事件,相當(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)聽值用法 useEffect(() => { //只有當(dāng)count的值發(fā)生變化,此函數(shù)才會(huì)執(zhí)行 console.log(`count change: count is ${count}`) }, [ count ]);
useCallback
先看一個(gè)最簡單的例子:
// 用于記錄 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)求。在這種場景下,沒有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)就誕生了…
先來分析下這段代碼的用意,Child組件是一個(gè)純展示型組件,其業(yè)務(wù)邏輯都是通過外部傳進(jìn)來的,這種場景在實(shí)際開發(fā)中很常見。
再分析下代碼的執(zhí)行過程:
- 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í)行一次,最簡單的方式當(dāng)然是將其從依賴列表中刪除。但如果裝了 hook 的lint 插件,會(huì)提示:React Hook useEffect has a missing dependency
useEffect(() => { getData();}, []);
實(shí)際情況很可能是當(dāng)getData改變的時(shí)候,是需要重新獲取數(shù)據(jù)的。這時(shí)就需要通過useCallback來將引用固定?。?/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è)要注意的是
在開始監(jiān)聽一個(gè)鼠標(biāo)的移動(dòng)的時(shí)候,想要?jiǎng)h除這個(gè)監(jiān)聽不生效,由于是, 加入useState導(dǎo)致組件再次渲染 handleMouse 函數(shù)在次渲染, handleMouse 作為組件內(nèi)的方法, 會(huì)跟著一同再次渲染, 并且在內(nèi)存里, 再次渲染出的 clickFunc !== 前clickFunc.
所以removeEventListener無法解除綁定, 再次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)文章
Reactjs?錯(cuò)誤邊界優(yōu)雅處理方法demo
這篇文章主要為大家介紹了Reactjs?錯(cuò)誤邊界優(yōu)雅處理方法demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12react腳手架構(gòu)建運(yùn)行時(shí)報(bào)錯(cuò)問題及解決
這篇文章主要介紹了react腳手架構(gòu)建運(yùn)行時(shí)報(bào)錯(cuò)問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03詳解如何封裝和使用一個(gè)React鑒權(quán)組件
JavaScript?和?React?提供了靈活的事件處理機(jī)制,特別是通過利用事件的捕獲階段來阻止事件傳播可以實(shí)現(xiàn)精細(xì)的權(quán)限控制,本文將詳細(xì)介紹這一技術(shù)的應(yīng)用,并通過實(shí)踐案例展示如何封裝和使用一個(gè)?React?鑒權(quán)組件,需要的可以參考下2024-03-03在react-antd中彈出層form內(nèi)容傳遞給父組件的操作
這篇文章主要介紹了在react-antd中彈出層form內(nèi)容傳遞給父組件的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-10-10antd之RangePicker設(shè)置默認(rèn)值方式
這篇文章主要介紹了antd之RangePicker設(shè)置默認(rèn)值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12React class和function的區(qū)別小結(jié)
Class組件和Function組件是React中創(chuàng)建組件的兩種主要方式,本文主要介紹了React class和function的區(qū)別小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10react如何實(shí)現(xiàn)側(cè)邊欄聯(lián)動(dòng)頭部導(dǎo)航欄效果
這篇文章主要介紹了react如何實(shí)現(xiàn)側(cè)邊欄聯(lián)動(dòng)頭部導(dǎo)航欄效果,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03