网站关键词优化外包服务,808影院网,wordpress淘客插件破解版,公司网站上线ReactHook中useState异步回调获取不到最新值及解决⽅案
预先了解 setState 的两种传参⽅式
1、直接传⼊新值 setState(options);
列如#xff1a;
const [state, setState] useState(0);
setState(state 1);
2、传⼊回调函数 setState(callBack);
例如#xff1a;
…ReactHook中useState异步回调获取不到最新值及解决⽅案
预先了解 setState 的两种传参⽅式
1、直接传⼊新值 setState(options);
列如
const [state, setState] useState(0);
setState(state 1);
2、传⼊回调函数 setState(callBack);
例如
const [state, setState] useState(0);
setState((prevState) prevState 1); // prevState 是改变之前的 state 值return 返回的值会作为新状态覆盖 state 值
useState 异步回调获取不到最新值及解决⽅案
通常情况下 setState 直接使⽤上述第⼀种⽅式传参即可但在⼀些特殊情况下第⼀种⽅式会出现异常
例如希望在异步回调或闭包中获取最新状态并设置状态此时第⼀种⽅式获取的状态不是实时的React 官⽅⽂档提到组件内部的任何函数包括事件处理函数和 Effect都是从它被创建的那次渲染中被「看到」的所以引⽤的值任然是旧的最后导致 setState 出现异常
import React, { useState, useEffect } from react;
const App () {
const [arr, setArr] useState([0]);
useEffect(() {
console.log(arr);
}, [arr]);
const handleClick () {
Promise.resolve().then(() {
setArr([...arr, 1]); // 此时赋值前 arr 为[0]
})
.then(() {
setArr([...arr, 2]); // 此时赋值前 arr 为旧状态仍然为[0]
});
}
return ( button onClick{handleClick}change/button
/
);
}
export default App;
上⾯代码App 组件实际也是个闭包函数handleClick ⾥⾯引⽤着 arr第⼀次 setArr 后 arr 的值确实更新了我们也可以在下⾯截图中看到但此次执⾏的 handleClick 事件处理函数作⽤域还是旧的⾥⾯引⽤的 arr 仍然为旧的导致第⼆次 setArr 后结果为 [0, 2]
在 class 组件中我们可以使⽤ setState(options, callBack); 在 setState 的第⼆个参数回调函数中再次进⾏ setState也不存在闭包作⽤域问题但是 React Hook 中 useState 移除了 setState 的第⼆个参数⽽且若嵌套太多也不佳
解决⽅案1推荐使⽤
将上述代码使⽤第⼆种回调⽅式传参
const handleClick () {
Promise.resolve().then(() {
setArr(prevState [...prevState, 1]); // 这⾥也可以不改使⽤第⼀中传参⽅式 setArr([...arr, 1]); 因为这⾥不需要获取最新状态
})
.then(() {
setArr(prevState [...prevState, 2]); // 这⾥必须改成回调函数传参⽅式否则会读取旧状态导致异常
});
}
解决⽅案2
使⽤ useReducer 仿造类组件中的 forceUpdate 实现组件强制渲染
import React, { useState, useReducer } from react;
const App () {
const [arr, setArr] useState([0]);
const [, forceUpdate] useReducer(x x 1, 0);
const handleClick () {
Promise.resolve().then(() {
arr.push(1); // 如果这⾥也需要做⼀次渲染在改变状态后调⽤ forceUpdate() 即可 })
.then(() {
arr.push(2);
forceUpdate();
});
}
return ( h1{arr.toString()}/h1
button onClick{handleClick}change/button
/
);
}
export default App;
点击前
点击后
解决⽅案3
利⽤ ref
import React, { useState, useRef, useEffect } from react;
const App () {
const [arr, setArr] useState([0]);
let ref useRef();
useEffect(() {
ref.current arr;
console.log(arr);
});
const handleClick () {
Promise.resolve().then(() {
const now [...ref.current, 1];
ref.current now;
setArr(now);
})
.then(() {
setArr([...ref.current, 2]);
});
}
return ( h1{arr.toString()}/h1
button onClick{handleClick}change/button
/
);
}
export default App;