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!
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>
);
};