Skip to content

Instantly share code, notes, and snippets.

@comp615
Created September 21, 2018 00:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save comp615/f99cb75d95739056755e583d80ec46f9 to your computer and use it in GitHub Desktop.
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
// 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