Skip to content

Instantly share code, notes, and snippets.

@bodia-uz
Created March 16, 2018 19:13
Show Gist options
  • Save bodia-uz/1de6cd185228ca184bae0389b23e2725 to your computer and use it in GitHub Desktop.
Save bodia-uz/1de6cd185228ca184bae0389b23e2725 to your computer and use it in GitHub Desktop.
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
// NOTE: `transition-duration` for modal css-animation is less then 500 ms
const MODAL_TRANSITION_DELAY = 500;
class ModalWithState extends Component {
constructor(props) {
super(props);
this.state = { isOpen: true };
}
render() {
const { isOpen } = this.state;
const { modalFn, onDismiss, onConfirm } = this.props;
return modalFn({
isOpen: isOpen,
onDismiss: (...args) => {
this.setState({ isOpen: false });
onDismiss(...args);
},
onConfirm: (...args) => {
this.setState({ isOpen: false });
onConfirm(...args);
}
});
}
}
function mountModal(modalFn, container) {
return new Promise((resolve, reject) => {
ReactDOM.render(
<ModalWithState
onDismiss={reject}
onConfirm={resolve}
modalFn={modalFn}
/>,
container
);
});
}
function unmountModal(container) {
ReactDOM.unmountComponentAtNode(container);
setTimeout(() => {
container.remove();
});
}
/**
* modal render function
*
* @callback modalFn
* @param {boolean} isOpen
* @param {function} onConfirm
* @param {function} onDismiss
*/
/**
* Open modal
* @param {function} modalFn - The callback that render modal.
*/
function modal(modalFn) {
const container = document.body.appendChild(document.createElement('div'));
if (typeof modalFn !== 'function') {
throw new Error('modalFn should be a function');
}
return mountModal(modalFn, container).then(
result => {
setTimeout(() => {
unmountModal(container);
}, MODAL_TRANSITION_DELAY);
return result;
},
error => {
setTimeout(() => {
unmountModal(container);
}, MODAL_TRANSITION_DELAY);
return Promise.reject(error);
}
);
}
export default modal;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment