React Hook中useState更新延遲問(wèn)題及解決
React Hook中useState更新延遲
方法一:去掉useEffect的第二個(gè)參數(shù)
例如以下代碼 錯(cuò)誤實(shí)例
const[zoom, setZoom] = useState(0); useEffect(() = >{ ? ? document.getElementById('workspace-content').addEventListener('mousewheel', scrollFunc); },[]); function scrollFunc(e) { ? ? setZoom(zoom + 5) }
會(huì)出現(xiàn)zoom永遠(yuǎn)等于 0+5, 而不是所謂的5, 10 ,15 為什么會(huì)這樣呢? 因?yàn)閡seEffect執(zhí)行時(shí),會(huì)創(chuàng)建一個(gè)閉包,在每次監(jiān)聽(tīng)到mousewheel運(yùn)行時(shí) 閉包內(nèi)部保存了zoom的初始化值 每次調(diào)用的時(shí)候都是取的初始化值0 所有會(huì)一直為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并將第二個(gè)參數(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)聽(tīng)此ref, 并實(shí)時(shí)跟useState同步
例如下面的代碼 錯(cuò)誤示例
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 每次都跟實(shí)際情況差一個(gè) 查閱資料發(fā)現(xiàn)useState必須要執(zhí)行完react整個(gè)生命周期才會(huì)獲取最新值
解決方案:用useRef中轉(zhuǎn),并實(shí)時(shí)同步給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ù)更新對(duì)象問(wèn)題
react hook 的useState更新是異步的,所以在連續(xù)更新出發(fā)useState時(shí)會(huì)出現(xiàn)問(wèn)題
eg:
import React, {useState} from 'react'; ? export default () => { ? ? const [obj, setObj] = useState({ ? ? ? ? a: 1, ? ? ? ? b: 2 ? ? ? }) ? ? ? const changeObj = () => { ? ? ? ? // 連續(xù)觸發(fā)2次setObj(實(shí)際項(xiàng)目不會(huì)這樣寫(xiě),我這樣寫(xiě)只是為了模擬連續(xù)觸發(fā)2次setObj帶來(lái)的問(wèn)題) ? ? ? ? setObj({...obj, a: 2}) ? ? ? ? setObj({...obj, b: 3})? ? ? } ? ?return (<div onClick={changeObj}> ? ? ? ? ? // 此時(shí)頁(yè)面上顯示的值為 {a: 1, b: 3}, 出現(xiàn)該問(wèn)題的原因是因?yàn)閡seState是異步的,在第二次觸發(fā)setObj時(shí),obj還是沒(méi)更新a之前的obj,所以出現(xiàn)該結(jié)果 ? ? ? ? ? ? {JSON.stringify(obj)} ? ? ? ? ? ?</div>) }
解決此情況的方式,就是在第二次觸發(fā)時(shí)使用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(實(shí)際項(xiàng)目不會(huì)這樣寫(xiě),為了模擬情況) ? ? ? ? setObj({...obj, a: 2}) ? ? ? ? // data標(biāo)識(shí)存儲(chǔ)的是更新a后的對(duì)象,用這樣的方式可以解決連續(xù)觸發(fā)2次帶來(lái)的問(wèn)題 ? ? ? ? setObj((data) => ({...data, b: 3}))? ? ? } ? ?return (<div onClick={changeObj}> ? ? ? ? ? // 此時(shí)頁(yè)面上顯示的值為 {a: 2, b: 3} ? ? ? ? ? ? {JSON.stringify(obj)} ? ? ? ? ? ?</div>) }
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
淺析JS中什么是自定義react數(shù)據(jù)驗(yàn)證組件
我們?cè)谧銮岸吮韱翁峤粫r(shí),經(jīng)常會(huì)遇到要對(duì)表單中的數(shù)據(jù)進(jìn)行校驗(yàn)的問(wèn)題。這篇文章主要介紹了js中什么是自定義react數(shù)據(jù)驗(yàn)證組件,需要的朋友可以參考下2018-10-10react quill中圖片上傳由默認(rèn)轉(zhuǎn)成base64改成上傳到服務(wù)器的方法
這篇文章主要介紹了react quill中圖片上傳由默認(rèn)轉(zhuǎn)成base64改成上傳到服務(wù)器的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10淺談對(duì)于react-thunk中間件的簡(jiǎn)單理解
這篇文章主要介紹了淺談對(duì)于react-thunk中間件的簡(jiǎn)單理解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05React中使用react-json-view展示JSON數(shù)據(jù)的操作方法
react-json-view是一個(gè)用于顯示和編輯javascript數(shù)組和JSON對(duì)象的React組件,本文給大家分享React中使用react-json-view展示JSON數(shù)據(jù)的操作方法,感興趣的朋友一起看看吧2023-12-12使用react-router4.0實(shí)現(xiàn)重定向和404功能的方法
本篇文章主要介紹了使用react-router4.0實(shí)現(xiàn)重定向和404功能的方法,具有一定的參考價(jià)值,有興趣的可以了解一下2017-08-08