React中Material UI Modal内函数每秒被多次调用如何解决?
问题原因
你遇到的高频调用问题本质是无限渲染循环,触发逻辑如下:
- 组件每次执行
render时,都会直接调用showModalContent()函数 showModalContent内部调用了getiframeUrl发起异步请求,请求成功后执行setState更新iframeUrlsetState会触发组件重新渲染,再次执行render,进而再次调用showModalContent发起请求、更新状态,无限往复,就出现了函数每秒被频繁调用的现象
补充说明:哪怕你Modal的open属性为false,{this.showModalContent()}这段代码也会在render执行时直接调用函数,而不是等Modal实际渲染子元素时才执行,所以就算Modal没打开,只要父组件有重渲染就会触发这个循环。
解决方案
核心原则是不要在渲染链路的函数中执行会触发重渲染的副作用操作,具体修改步骤如下:
- 把
iframeUrl的请求逻辑从showModalContent中移除,放到Modal打开的触发函数handleShowModal里,只在Modal打开时请求一次地址 - 改造
showModalContent为纯渲染函数,内部不包含任何修改状态、发起请求的副作用逻辑 - 可选优化:如果不需要在Modal关闭时保留之前的iframe地址,可以在关闭Modal时重置
iframeUrl,减少内存占用
修改后的参考代码:
class ComponentName extends React.Component { constructor(props) { super(props); this.state = { countries: [], isButtonDisabled: false, formError: false, showModalCta: false, showModal: false, iframeUrl: '' }; } handleClose = () => { this.setState({ showModal: false, // 可选:关闭时清空地址 iframeUrl: '' }); }; handleShowModal = () => { // 只在打开Modal的时候请求iframe地址,避免重复调用 getiframeUrl().then((res) => { // 可选优化:仅Modal仍处于打开状态时才更新状态,避免闭包导致的无用更新 if (this.state.showModal) { this.setState({ iframeUrl: res.level2VerificationUrl }); } }); this.setState({ showModal: true }) } // 改造为纯渲染函数,无副作用 showModalContent = () => { const { classes } = this.props; const { iframeUrl } = this.state; return ( <Paper className={classes.modalPaper}> <iframe src={iframeUrl} width="500px" height="500px" /> </Paper> ); }; render() { const { classes, history, firstName, lastName, country, region, address, city, dob, phone, smsCode, postalCode, actions } = this.props; const { countries, formError, isButtonDisabled, showCta, showModal } = this.state; return ( <div> <Modal className={classes.modal} open={showModal} onClose={this.handleClose}> {this.showModalContent()} </Modal> </div> ); } }
内容的提问来源于stack exchange,提问作者Kenny Quach
相关产品推荐
相关产品推荐

