網(wǎng)站首頁 編程語言 正文
React Hook中useState更新延遲
方法一:去掉useEffect的第二個參數(shù)
例如以下代碼 錯誤實例
const[zoom, setZoom] = useState(0);
useEffect(() = >{
? ? document.getElementById('workspace-content').addEventListener('mousewheel', scrollFunc);
},[]);
function scrollFunc(e) {
? ? setZoom(zoom + 5)
}
會出現(xiàn)zoom永遠(yuǎn)等于 0+5, 而不是所謂的5, 10 ,15 為什么會這樣呢? 因為useEffect執(zhí)行時,會創(chuàng)建一個閉包,在每次監(jiān)聽到mousewheel運行時 閉包內(nèi)部保存了zoom的初始化值 每次調(diào)用的時候都是取的初始化值0 所有會一直為0+5
怎么解決呢?
解決方案: 去掉useEffect中的空數(shù)組即可
const[zoom, setZoom] = useState(0);
useEffect(() = >{
? ? document.getElementById('workspace-content').addEventListener('mousewheel', scrollFunc);
? ? return () = >document.getElementById('workspace-content').removeEventListener("mousewheel", scrollFunc); // 記得解綁事件
});
function scrollFunc(e) {
? ? setZoom(zoom + 5)
}
方法二:將改變函數(shù)移入useEffect并將第二個參數(shù)設(shè)置為state
依舊用上面的例子
解決方法:正確示例
useEffect(() = >{
? ? document.getElementById('workspace-content').addEventListener('mousewheel', scrollFunc);
? ? return () = >document.getElementById('workspace-content').removeEventListener("mousewheel", scrollFunc);
? ? function scrollFunc(e) {
? ? ? ? setZoom(zoom + 5) e.preventDefault()
? ? }
},[zoom]);
方法三:使用Ref, 在useEffect內(nèi)監(jiān)聽此ref, 并實時跟useState同步
例如下面的代碼 錯誤示例
const [currentIndex, setCurrentIndex] = useState(0)
? const handleLeft = () => {
? ? ?setCurrentIndex(currentIndex+ 1)
? ? ?console.log(currentIndex)
? }
初始化currentIndex為0 每次執(zhí)行handleLeft函 數(shù)是讓currentIndex加1, 之后立即獲取currentIndex的值發(fā)現(xiàn) 第一次執(zhí)行currentIndex = 0
第二次執(zhí)行currentIndex = 1 每次都跟實際情況差一個 ?查閱資料發(fā)現(xiàn)useState必須要執(zhí)行完react整個生命周期才會獲取最新值
解決方案:用useRef中轉(zhuǎn),并實時同步給useState?
const [currentIndex, setCurrentIndex] = useState(0)
const currentIndexRef = useRef(0);
? const handleLeft = () => {
? ? ?currentIndexRef.current += 1
? ? ?console.log(currentIndexRef.current)
? }
useEffect(()=>{
? ? setCurrentIndex(currentIndexRef.current)
},[currentIndexRef.current])
React Hook useState連續(xù)更新對象問題
react hook 的useState更新是異步的,所以在連續(xù)更新出發(fā)useState時會出現(xiàn)問題
eg:?
import React, {useState} from 'react';
?
export default () => {
? ? const [obj, setObj] = useState({
? ? ? ? a: 1,
? ? ? ? b: 2
? ? ? })
?
? ? const changeObj = () => {
? ? ? ? // 連續(xù)觸發(fā)2次setObj(實際項目不會這樣寫,我這樣寫只是為了模擬連續(xù)觸發(fā)2次setObj帶來的問題)
? ? ? ? setObj({...obj, a: 2})
? ? ? ? setObj({...obj, b: 3})?
? ? }
? ?return (<div onClick={changeObj}>
? ? ? ? ? // 此時頁面上顯示的值為 {a: 1, b: 3}, 出現(xiàn)該問題的原因是因為useState是異步的,在第二次觸發(fā)setObj時,obj還是沒更新a之前的obj,所以出現(xiàn)該結(jié)果
? ? ? ? ? ? {JSON.stringify(obj)}
? ? ? ? ? ?</div>)
}
解決此情況的方式,就是在第二次觸發(fā)時使用setObj((data) => ({...data, b: 3})) 這樣的方式
import React, {useState} from 'react';
?
export default () => {
? ? const [obj, setObj] = useState({
? ? ? ? a: 1,
? ? ? ? b: 2
? ? ? })
?
? ? const changeObj = () => {
? ? ? ? // 連續(xù)觸發(fā)2次setObj(實際項目不會這樣寫,為了模擬情況)
? ? ? ? setObj({...obj, a: 2})
? ? ? ? // data標(biāo)識存儲的是更新a后的對象,用這樣的方式可以解決連續(xù)觸發(fā)2次帶來的問題
? ? ? ? setObj((data) => ({...data, b: 3}))?
? ? }
? ?return (<div onClick={changeObj}>
? ? ? ? ? // 此時頁面上顯示的值為 {a: 2, b: 3}
? ? ? ? ? ? {JSON.stringify(obj)}
? ? ? ? ? ?</div>)
}
原文鏈接:https://blog.csdn.net/qq_35493664/article/details/105195549
相關(guān)推薦
- 2023-01-28 flutter消息推送客戶端集成方案詳解_Android
- 2022-02-01 使用 file_get_contents 獲取網(wǎng)站信息報錯failed to open stream
- 2022-01-30 axios自帶的上傳進(jìn)度回調(diào)函數(shù)
- 2022-07-03 級聯(lián)分類器算法原理解析_相關(guān)技巧
- 2022-04-02 nginx網(wǎng)頁緩存時間的配置過程_nginx
- 2024-02-27 Action獲取表單提交數(shù)據(jù)
- 2023-02-17 C++可執(zhí)行文件絕對路徑值與VS安全檢查詳解_C 語言
- 2021-12-31 linux下RPM包安裝基于xinetd的服務(wù)的管理_Linux
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支