我有一段代码正在关注一些正在修改我的 React State 的异步函数。但问题是,在解决所有承诺后启动其他功能时,该功能没有我的状态的更新版本:
const [myState, setMyState] = useState<myType>({...});
const pendingPromises: Promise<void>[] = [];
async function asyncFunction(foo: any){
// Do stuff that changes myState
setMyState((myState) => myStateModified);
function doStuffWithUpdatedState(){
console.log(myState) // This shows the original state before it has been modified by asyncFunction()
}
function mainFunction(){
myArray.forEach((a) => pendingPromises.push(asyncFunction(a))
Promise.all(pendingPromises).then(doStuffWithUpdatedState)
}
因此,为了解决这个问题,我声明了一个新状态,当我需要调用第二个函数时,我将其更改为 true:
const [myState, setMyState] = useState<myType>({...});
const [callFunction, setCallFunction] = useState<boolean>(false);
const pendingPromises: Promise<void>[] = [];
useEffect(() => {
if (callFunction) {
doStuffWithUpdatedState();
setCallFunction(false);
}
}, [callFunction]);
async function asyncFunction(foo: any){
// Do stuff that changes myState
setMyState((myState) => myStateModified);
function doStuffWithUpdatedState(){
console.log(myState) // This shows the original state before it has been modified by asyncFunction()
}
function mainFunction(){
myArray.forEach((a) => pendingPromises.push(asyncFunction(a))
Promise.all(pendingPromises).then(() => setCallFunction(true)) // calling function
}
这是可行的,但感觉不太干净。 这样的做法好吗?如果没有,我该怎么办?
通常在这种情况下,相关函数正在改变状态,因此使用状态设置器的回调形式是简单的解决方案。但你说过
doStuffWithUpdatedState
不会改变状态。
既然如此,最好不要仅仅为了调用函数而设置状态标志来导致重新渲染。
这里有一些替代方案:
你可以继续使用状态设置器的回调形式,只需返回收到的相同状态,使状态更新调用不执行任何操作:
function doStuffWithUpdatedState(){
setMyState((state) => {
// ...use `state`, which is the up-to-date state information...
return state; // Return state unchanged
});
}
我已经这样做过几次了,但从来都不满意。 :-)
您可以使用
ref
始终可以访问最新状态:
const [myState, setMyState] = useState<myType>({/*...*/});
const refMyState = useRef(null);
refMyState.current = myState;
// ...
function doStuffWithUpdatedState(){
const state = refMyState.current;
// ...use `state`, which is the up-to-date state information...
}
使用其他机制来存储
myState
而不是useState
,例如Redux。 (这样做是一个足够大的改变,我不会做一个例子,他们的文档已经涵盖了它。)