網站首頁 編程語言 正文
開始之前請注意這句話:任何優化都會增加復雜性,任何過早添加的優化都會帶來風險,因為優化后的代碼可能會多次更改
useEffect
相關作用:監聽 & 初始化
//最簡單用法
useEffect(() => {
//只有方法體,相當于componentDidMount和componentDidUpdate中的代碼
document.title = count;
})
//加返回值用法
useEffect(() => {
//添加監聽事件,相當于componentDidMount和componentDidUpdate中的代碼
window.addEventListener('resize', onChange, false);
//返回的函數用于解綁事件,相當于componentWillUnmount中的代碼
return () => {
window.removeEventListener('resize', onChange, false)
}
})
//加空數組參數用法
useEffect(() => {
// 相當于 componentDidMount
window.addEventListener('resize', onChange, false)
return () => {
// 相當于 componentWillUnmount
window.removeEventListener('resize', onChange, false)
}
}, []);
//加監聽值用法
useEffect(() => {
//只有當count的值發生變化,此函數才會執行
console.log(`count change: count is ${count}`)
}, [ count ]);
useCallback
先看一個最簡單的例子:
// 用于記錄 getData 調用次數
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模擬發起網絡請求。在這種場景下,沒有useCallback什么事,組件本身是高內聚的。
如果涉及到組件通訊,情況就不一樣了:
// 用于記錄 getData 調用次數
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>;}
就這么輕輕松松,一個死循環就誕生了…
先來分析下這段代碼的用意,Child組件是一個純展示型組件,其業務邏輯都是通過外部傳進來的,這種場景在實際開發中很常見。
再分析下代碼的執行過程:
- App渲染Child,將val和getData傳進去
- Child使用useEffect獲取數據。因為對getData有依賴,于是將其加入依賴列表
- getData執行時,調用setVal,導致App重新渲染
- App重新渲染時生成新的getData方法,傳給Child
- Child發現getData的引用變了,又會執行getData
- 3 -> 5 是一個死循環
如果明確getData只會執行一次,最簡單的方式當然是將其從依賴列表中刪除。但如果裝了 hook 的lint 插件,會提示:React Hook useEffect has a missing dependency
useEffect(() => {
getData();}, []);
實際情況很可能是當getData改變的時候,是需要重新獲取數據的。這時就需要通過useCallback來將引用固定?。?/p>
const getData = useCallback(() => {
setTimeout(() => {
setVal("new data " + count);
count++;
}, 500);}, []);
上面例子中getData的引用永遠不會變,因為他它的依賴列表是空??梢愿鶕嶋H情況將依賴加進去,就能確保依賴不變的情況下,函數的引用保持不變。
還有一個要注意的是
在開始監聽一個鼠標的移動的時候,想要刪除這個監聽不生效,由于是, 加入useState導致組件再次渲染 handleMouse 函數在次渲染, handleMouse 作為組件內的方法, 會跟著一同再次渲染, 并且在內存里, 再次渲染出的 clickFunc !== 前clickFunc.
所以removeEventListener無法解除綁定, 再次addEventListener則會綁定一個新方法.
document.addEventListener('mousemove',handleMouse,true)
解決方案 : useCallback 緩存改方法 這時候的 document.removeEventListener(‘mousemove’,handleMouse,true) 中的handleMouse 和添加中的方法就是一個了,就能刪除了。
onst handleMouse= useCallback(() => {
//xxxx
console.log("clicking");
}, []);
原文鏈接:https://blog.csdn.net/weixin_42910765/article/details/128344167
相關推薦
- 2022-03-22 nginx開啟gzip壓縮的完整步驟記錄_nginx
- 2022-07-18 CSS基礎語法和盒模型
- 2023-04-10 Python中mmap模塊處理大文本的操作方法_python
- 2022-04-18 python?ConfigParser庫的使用及遇到的坑_python
- 2022-10-01 Python函數參數基礎介紹及示例_python
- 2022-09-10 Go語言的反射機制詳解_Golang
- 2022-08-21 Android設置重復文字水印背景的方法_Android
- 2023-03-29 Pytorch中的數據轉換Transforms與DataLoader方式_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支