reactjs - setState 没有及时更新以更新我的视图
问题描述
我对 React 很陌生,最近从 Angular 迁移过来。我发现使用 setState 更新变量状态的速度不够快,无法反映在我的 render() 中。我想在用户单击按钮后立即显示加载程序,并在关闭按钮后立即隐藏它。但是,当我单击加载图标时,它不会立即显示,并且由于 setState() 的异步行为,显示会略有延迟。是否有任何解决方法。
constructor(props) {
this.state= {
displayExportLoading: false
}
}
download() {
this.setState({ displayExportLoading: true});
// async actions of fetching and rendering elements
// promise is complete
Promise.all(options)
.then(() => {
this.setState({displayExportLoading:false});
})
}
render() {
var loadingOnExport = this.state.displayExportLoading? <img src= {loaderExport} width="30px"/>:''
return(
<button onClick={this.download}>Download</button>
<div>
{loadingOnExport}
</div>
)
}
我想在单击按钮后立即显示加载程序图像,而不是稍有延迟。这可以在没有状态变量的情况下实现吗?
编辑1:
constructor(props) {
this.state= {
displayExportLoading: false
}
}
download() {
this.setState({ displayExportLoading: true});
var pageCount;
var doc = new jsPDF("p", "mm");
var pos = 20;
var gapBetweenImages= 40;
metrics = metrics.map(async (key, index) => {
let id_val = `graph-id-${index}`; // creating IDs
const input = document.getElementById(id_val);
// html to pdf
let canvas = await html2canvas(input,[1300,1300]);
const imgData = canvas.toDataURL("image/JPEG");
var imgWidth =canvas.width / 8;
var imgHeight = canvas.height * imgWidth / canvas.width;
if(index % 2== 0 && index !== 0) {
pos = 20;
doc.addPage();
}
if( index %2 == 1) {
pos = imgHeight + gapBetweenImages;
}
doc.addImage(imgData, "JPEG", 15, pos, imgWidth, imgHeight);
// doc.addPage();
console.log("image data",imgData)
pageCount = doc.internal.getNumberOfPages();
});
Promise.all(metrics)
.then(() => {
doc.deletePage(pageCount);
doc.save("file.pdf");
this.setState({ displayExportLoading: false })
})
.catch(err => console.log(err));
});
}
render() {
var loadingOnExport = this.state.displayExportLoading? <img src= {loaderExport} width="30px"/>:''
return(
<button onClick={this.download}>Download</button>
<div>
{loadingOnExport}
</div>
)
}
解决方案
通过利用 setState() 回调(第二个参数)尝试以下操作,仅displayExportLoading
在设置为true
. 从setState()的文档中:
setState() 并不总是立即更新组件。它可能会批量更新或将更新推迟到以后。这使得在调用 setState() 之后立即读取 this.state 是一个潜在的陷阱。相反,使用 componentDidUpdate 或 setState 回调 (setState(updater, callback)),它们都保证在应用更新后触发。如果您需要根据之前的状态设置状态,请阅读下面的 updater 参数。
download() {
this.setState({ displayExportLoading: true }, () => {
// async actions of fetching and rendering elements
// promise is complete
Promise.all(options)
.then(() => {
this.setState({displayExportLoading:false});
})
});
}
另一种选择可能是使用 CSS可见性来显示/隐藏<img />
而不是从 DOM 中添加/删除它:
render() {
const { displayExportLoading } = this.state;
return (
<button onClick={this.download}>Download</button>
<div style={{ visibility: displayExportLoading ? 'visible' : 'hidden' }}>
<img src={loaderExport} width="30px" />
</div>
);
}
希望这会有所帮助!
推荐阅读
- python - 如何为同一个项目链接2个python脚本
- c++ - 16 到 32 位整数转换与性能
- ios - iOS ARKit 应用程序:如何在不旋转内部相机视图的情况下旋转 UI(屏幕)?
- javascript - 关于简单 Javascript/HTML 的问题
- javascript - 俄罗斯方块 on Java Script 键控问题
- javascript - 复选框按关键字选择?
- javascript - 使用 CocoaPods 捆绑 React Native iOS 应用程序的问题
- android - 如何处理 Android SQLite 数据库中的“inf”值?
- ruby-on-rails - 认证请求规范
- python - 如何减少多个重叠 matplotlib loglog 图的内存开销?