Last active
December 26, 2017 13:10
-
-
Save blvdmitry/dbf558b016e384632d2af32482ffac84 to your computer and use it in GitHub Desktop.
tooltip
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @flow | |
import * as React from 'react'; | |
import { connect } from 'react-redux'; | |
import { Gateway } from 'react-gateway'; | |
import get from 'lodash/get'; | |
import cssVars from 'sj/css/variables/animations.scss'; | |
import { hideModal, hideModalWithoutNavigation, showModal, addModal, removeModal } from 'sj/actions/modalActions'; | |
import { MODAL_QUERY_PARAM, MODAL_GATEWAY_NAME } from 'sj/constants/modals'; | |
import ModalManagerHolder from '../ModalManagerHolder/ModalManagerHolder'; | |
type OwnProps = { | |
children?: ReactElementType, | |
id: string, | |
modalKey?: number | string, | |
onClose?: Function, | |
withUrl?: boolean, | |
disableOutsideClick?: boolean, | |
} | |
type Props = OwnProps & { | |
dispatch: Dispatch, | |
stateKey: string, | |
shown: boolean, | |
isModalRoute: boolean, | |
}; | |
export type ModalManagerPortalPropsType = OwnProps; | |
type State = { | |
unmountLocked: boolean, | |
}; | |
const UNMOUNT_TIMEOUT = parseInt(cssVars.modalsAnimationTime, 10); | |
class ModalManagerPortal extends React.PureComponent<Props, State> { | |
state = { | |
unmountLocked: false, | |
}; | |
rendered; | |
componentDidMount() { | |
const { dispatch, isModalRoute, id, modalKey, withUrl } = this.props; | |
const payload = { id, modalKey, withUrl }; | |
this.rendered = true; | |
dispatch(addModal(payload)); | |
if (isModalRoute) { | |
dispatch(showModal({ ...payload, isInitial: true })); | |
} | |
} | |
componentWillUnmount() { | |
const { dispatch, id, modalKey } = this.props; | |
const payload = { id, modalKey }; | |
this.rendered = false; | |
dispatch(removeModal(payload)); | |
} | |
componentWillReceiveProps(nextProps) { | |
const { shown } = this.props; | |
// Оставляем модалку в доме на время анимации закрытия | |
if ((nextProps.shown !== shown) && !nextProps.shown) { | |
this.setState({ unmountLocked: true }); | |
setTimeout(() => { | |
if (this.rendered) this.setState({ unmountLocked: false }); | |
}, UNMOUNT_TIMEOUT); | |
} | |
} | |
handleClickOutside = () => { | |
const { dispatch, onClose, disableOutsideClick } = this.props; | |
if (disableOutsideClick) return; | |
dispatch(hideModal()); | |
if (onClose) { | |
onClose(); | |
} | |
}; | |
handleBack = () => { | |
const { dispatch, onClose } = this.props; | |
dispatch(hideModalWithoutNavigation()); | |
if (onClose) { | |
onClose(); | |
} | |
}; | |
render() { | |
const { shown } = this.props; | |
const { unmountLocked } = this.state; | |
if (!shown && !unmountLocked) { | |
return null; | |
} | |
const { id, data, stateKey, children } = this.props; | |
const childrenWithProps = React.Children.map(children, (child) => { | |
return React.cloneElement(child, { ...data, id }); | |
}); | |
return ( | |
<Gateway into={MODAL_GATEWAY_NAME}> | |
<ModalManagerHolder | |
stateKey={stateKey} | |
onClickOutside={this.handleClickOutside} | |
onBack={this.handleBack} | |
> | |
{ childrenWithProps } | |
</ModalManagerHolder> | |
</Gateway> | |
); | |
} | |
} | |
const mapStateToProps = ({ modals, currentRoute }, { id, modalKey }: OwnProps) => { | |
// Во доме сидят такие куча порталов и ждут, огда они в stack окажутся последними | |
// Да так, чтобы роут еще с нужным параметром был | |
const { routeParams } = currentRoute; | |
const modalRouteKey = routeParams[MODAL_QUERY_PARAM]; | |
const stack = get(modals, 'stack', []); | |
const data = get(modals, 'data', {}); | |
const stateKey = modalKey ? `${id}:${modalKey}` : id; | |
const shown = stack[stack.length - 1] === stateKey; | |
const isModalRoute = stateKey === modalRouteKey; | |
return { stateKey, data, shown, isModalRoute }; | |
}; | |
export default connect(mapStateToProps)(ModalManagerPortal); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment