[React] Create a Query Parameter Modal Route with React Router
Routes are some times better served as a modal. If you have a modal (like a login modal) that needs to be routeable and appear on all pages you may need to use query params. Will explore how to render a route all the time and use query params to control when it's content renders.
Modal should be created as a 'Portal':
<body> <noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"></div> <div id="modal_root"></div> </body>
import React, { Component } from "react"; import { createPortal } from "react-dom"; const modalStyle = { position: "fixed", left: 0, top: 0, bottom: 0, right: 0, backgroundColor: "rgba(0,0,0,.2)", color: "#FFF", fontSize: "40px", }; export default class Modal extends Component { render() { return createPortal( <div style={modalStyle} onClick={this.props.onClick}> {this.props.children} </div>, document.getElementById("modal_root"), ); } }
If we want to show the Modal everywhere in the page, we need to declear the Router outside 'Switch' component:
import React from "react"; import ReactDOM from "react-dom"; import "./index.css"; import { BrowserRouter, Switch, Route } from "react-router-dom"; import HomePage from "./pages/home"; import ProfilePage from "./pages/profile"; import Login from "./pages/login"; const routes = ( <BrowserRouter> <Switch> <Route exact path="/" component={HomePage} /> <Route path="/profile" component={ProfilePage} /> </Switch> <Route path="/" component={Login} /> </BrowserRouter> ); ReactDOM.render(routes, document.getElementById("root"));
For all the routes re-render, Login component will be shown.
Inside Login componnet, control the component show / hide by query param:
import React, { Component } from "react"; import Modal from "./modal"; export default class LoginPage extends Component { render() { let params = new URLSearchParams(this.props.location.search); return ( params.get("login") && ( <Modal onClick={() => { this.props.history.push(this.props.location.pathname); }} > <div style={{ display: "flex", alignItems: "center", justifyContent: "center", height: "100%", }} > Login modal </div> </Modal> ) ); } }
Using:
<Link to={{ pathname: "/", search: "?login=true" }}>Login</Link>