我的顶级函数组件 App
有一个返回 Promise 的函数 req()
,它将被许多子组件调用。在内部,req()
更新 App
的状态以显示它被调用(以及为什么),然后调用不同的承诺返回函数。这是req()
:
//wrap all requests to track and display their progress
function req(func, args, waitCap, yayCap) {
//perform a callback on a given req, then update state
const withReq = (argId, callback) => {
let newReqs = state.reqList.map ( r => r); //copy the reqList
for (let reqIndex = 0; reqIndex < newReqs.length; reqIndex++) { //iterate through the list
if ((newReqs[reqIndex] && (newReqs[reqIndex].id === argId))) { //find a match
callback(newReqs[reqIndex]); //pass it to the callback
break;
}
}
setState( prevState => ({
...prevState,
reqList:newReqs,
}));
}
//kill a req and update state
const deleteReq = argId => {
let newReqs = state.reqList.filter( r => { //new reqList is the same list with no objects containing the argID
return r.id !== argId;
});
setState( prevState => ({
...prevState,
reqList:newReqs,
}));
}
//duplicate the req list
let newReqs = state.reqList.map( r => r );
const now = new Date(); //create a unique ID for this req for tracking
const reqId = [
now.getFullYear(),
String(now.getMonth()+1).padStart(2,"0"),
String(now.getDate()).padStart(2,"0"),
String(now.getHours()).padStart(2,"0"),
String(now.getMinutes()).padStart(2,"0"),
String(now.getSeconds()).padStart(2,"0"),
String(Math.floor(Math.random()*10000)).padStart(4,"0"),
].join("");
newReqs.push({ //add the new req to the new reqList
status:"waiting",
caption:waitCap,
id:reqId,
});
setState( prevState => ({ //render the changed list of Reqs
...prevState,
reqList:newReqs,
}));
return ServerCalls[func](args)
.then((res)=>{
withReq(reqId, foundReq =>{ //update the req to show success
foundReq.status="success";
foundReq.caption=yayCap;
});
setTimeout(() => {
deleteReq(reqId); //remove it from display after 3 seconds
}, 3000);
return res;
})
.catch((err)=>{
withReq(reqId, foundReq =>{ //update the req to show failure
foundReq.status="failure";
foundReq.caption=foundReq.caption+" Failed!";
});
setTimeout(() => {
deleteReq(reqId); //remove it from display after 3 seconds
}, 3000);
throw err;
})
}
这里的问题是 Promise.then()
和 Promise.catch()
中的回调函数对状态的初始值进行操作,而不是由于作用域的原因,它在回调执行时具有的值。这不是类组件的问题,只是功能组件的问题。
有没有办法让功能组件从回调中读取其执行时状态?或者是否需要解决方法?
答案 0 :(得分:0)
这里有两个问题:
withReq(reqId, foundReq => { //update the req to show success
foundReq.status = "success";
foundReq.caption = yayCap;
});
永远不要在 React 中改变状态 - 它会导致重新渲染问题。
.then
回调中的值已过时。通过将状态设置器函数中的当前(新更新)状态而不是旧状态传递给 callback
来解决此问题:const withReq = (argId, callback) => {
setState(prevState => ({
...prevState,
reqList: prevState.reqList.map(req => (
req.id === argId ? callback(req) : req
)),
}));
}
然后确保 callback
不会变异,而是创建并返回一个新对象,例如:
withReq(reqId, foundReq => ({
...foundReq,
status: "success",
caption: yayCap,
}));