Created
September 21, 2018 00:24
-
-
Save comp615/f99cb75d95739056755e583d80ec46f9 to your computer and use it in GitHub Desktop.
One approach to creating a site-wide modal system with React Router 4+. Relies on routes being evaluated in place to split the location context magically
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
// Allows a route and screen to just exist, and let's the app figure out if it should be a modal or not | |
// and manage the background context | |
------------- | |
<Router> | |
<App> | |
<ModalSwitch> | |
<ModalRoute | |
component={RecipientsScreen} | |
exact | |
path='/keyboard_shortcuts' | |
/> | |
<Route component={MainScreen} exact path='/' /> | |
</ModalSwitch> | |
</App> | |
</Router> | |
------------ | |
// Same logic as switch, but checks if a route can be shown as a modal and if so wraps it, | |
// showing two different pages at the same time to get a routed-modal effect | |
class ModalSwitch { | |
_shouldShowAsModal = () => { | |
// Look down all routes for a match, check if it's a modalable route | |
// check some other conditions and such | |
}; | |
render() { | |
const { location, history } = this.props; | |
const showAsModal = this._shouldShowAsModal() | |
return ( | |
<View style={styles.root}> | |
{ /* Optional modal route on top */ } | |
{showAsModal ? ( | |
<Modal {...this._modalOptions} history={history} location={location}> | |
<Switch>{this.props.children}</Switch> | |
</Modal> | |
) : null} | |
{ /* Either normal routes, or the last non-modal route */ } | |
{!showAsModal || this.backgroundLocation ? ( | |
// Alter the child location context so that everything uses the new computed location | |
// This would need to be wrapped normally | |
<SwitchWithOldLocationContext> | |
{this.props.children} | |
</SwitchWithOldLocationContext> | |
) : null} | |
</View> | |
); | |
} | |
} | |
class Modal extends React.Component<Props> { | |
render() { | |
const { children } = this.props; | |
return ( | |
<Layer.Modal> | |
<ModalContext> | |
<ModalSheet | |
onMaskClick={this._handleMaskClick} | |
withMask | |
> | |
<View | |
aria-labelledby={A11yDomIds.modalHeaderId} | |
aria-modal | |
children={children} | |
role="dialog" | |
/> | |
</ModalSheet> | |
</ModalContext> | |
</Layer.Modal> | |
); | |
} | |
} | |
export default Modal; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment