【发布时间】:2021-04-05 17:30:15
【问题描述】:
如果反应代码有问题,由于某种原因,当我从 MyApp.promise().then(<here>) 更新 UI 时,一切都按预期工作,但在我的 MyApp.promise().then().catch(<here>) 中却没有
- 我知道代码实际上已执行到我实际调用
setData时,这是我的useState()返回函数 - 在
then()中调用该函数可以正常工作,而不是在catch() - 最终触发
catch()的异常工作正常,因为catch()按预期执行 - 我在组件中添加了一个
console.log(),当更新来自catch()时,我看到它不再重新绘制
我想我的问题是:catch() 函数有什么特别之处,所以 react 不会起作用?
这是我的应用程序挂钩处理升级状态更新的代码:
const useUpdateStatus = () => {
const [data,setData] = useState({status: STATUS.IDLE,changelog:null,tasks:[]})
const updateData = (d) => {
// We call setData with an anonymous function so we can merge previous
// data with new data
setData((prev) => {
console.log({ ...prev, ...d })
return { ...prev, ...d }
})
};
// Only once, we set the timer to periodically update status
useEffect(() => {
setInterval(() => {
MyApp.get('/system/upgrade')
.then((upgrade) => {
// If anything is not "pending", it means we are upgrading
for (var t of upgrade.tasks) {
if (t.status !== "pending") {
updateData({ status: STATUS.INSTALLING})
}
}
// updateData will call setData with the full status
// This works as intended, UI is updated on each step
updateData({ tasks: upgrade.tasks, changelog: upgrade.changelog})
})
.catch((e) => {
// If data can't be fetched, it probably means we are restarting
// services, so we updated the tasks array accordingly
setData((prev) => {
for (var t of prev.tasks) {
if (t['id'] === "restarting") {
t['status'] = 'running'
}
else if (t['status'] == "running") {
t['status'] = 'finished'
}
}
// The expected data is logged here
console.log(prev)
return prev
})
})
}, 1000);
},[])
return data
}
这是表示层:
// Using the hook :
const { changelog, tasks, status } = useUpdateStatus()
// Somewhere int he page :
<UpdateProgress tasks={tasks}/>
// The actual components :
const UpdateProgress = (props) => {
return(
<div style={{display: "flex", width: "100%"}}>
{ props.tasks.map(s => {
return(
<UpdateTask key={s.name} task={s}/>
)
})}
</div>
)
}
const UpdateTask = (props) => {
const colors = {
"pending":"LightGray",
"running":"SteelBlue",
"finished":"Green",
"failed":"red"
}
return(
<div style={{ textAlign: "center", flex: "1" }}>
<Check fill={colors[props.task.status]} width="50px" height="50px"/><br/>
<p style={props.task.status==="running" ? {fontWeight: 'bold'} : { fontWeight: 'normal'}}>{props.task.name}</p>
</div>
)
}
【问题讨论】: