I am using React and rendering a modal from Material UI. The way the modal is rendered is it has to be a part of the body of code. So I added it to the bottom of the page. The state determines whether or not the modal is open. The issue is that I can see that a function that is in the modal is being called multiple times. And very rapidly. Like more than once each second. Please see my code:
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
});
};
handleShowModal = () => {
this.setState({
showModal: true
})
}
showModalContent = () => {
const { classes } = this.props;
const { iframeUrl } = this.state;
getiframeUrl().then((res) => {
this.setState({
iframeUrl: res.level2VerificationUrl
});
});
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>
);
}
}
Its pretty much calling that function to get the url every second. But I dont quite understand why this is the behavior. Been doing research on this but no answers. Is there any way to prevent this? Thanks!
CodePudding user response:
showModalContent will be executed on every "state change" of the component (on every render). There (from what I see) you are making a call to a promise (getiframeUrl) and you are setting the state of the component (which makes it change state).
Hence: Render -> showModalContent -> change state -> re-render -> showModalContent -> ... (infinite loop).
My advice is that you do the setState of iframeUrl only in the componentDidMount. Something like this:
componentDidMount() {
const { iframeUrl } = this.state;
getiframeUrl().then((res) => {
this.setState({
iframeUrl: res.level2VerificationUrl
});
});
}
showModalContent = () => {
const { classes } = this.props;
return (
<Paper className={classes.modalPaper}>
<iframe src={iframeUrl} width="500px" height="500px" />
</Paper>
);
};