Render modal on a route with the parent route rendered in background

Viewed 5102

I'm using ReachUI Dialog to render a Dialog (Modal). The Dialog is routable at the route products/create/, as you can see in the code below.

Is it possible to render both the ProductsTable (which is located at the parent route products/) and the Dialog, when I route to products/create so that I can see the ProductsTable component in the background of the modal? I'm hoping to achieve this with react-router.

This is what the code looks like now:

...
import { Switch, Route, useRouteMatch, match, useHistory, } from "react-router-dom";
import { Dialog } from "@reach/dialog";

export function ProductsPage() {
  const { url }: match = useRouteMatch();
  const { push } = useHistory();

  const gotToCreateProduct = () => push(`${url}/create`);

  return (
      <Switch>
        <Route exact path={url}>
          <Page title="Products" onCreateButtonClick={gotToCreateProduct}>
            <ProductsTable></ProductsTable>
          </Page>
        </Route>
        <Route path={`${url}/create`}>
            <Dialog isOpen={true} onDismiss={() => push(url)}>
                <ProductForm></ProductForm>
            </Dialog>
        </Route>
      </Switch>
  );
}
4 Answers

Figured it out myself, basically you just have to put 2 Switch components next to each other, and remove the exact attribute of the parent Route. This way, both Switches will have a match and render their routes. Makes sense & it works.

    return (
        <>
            <Switch>
                <Route path={url}>
                    <Page title="Products" onCreateButtonClick={gotToCreateProduct}>
                        <ProductsTable></ProductsTable>
                    </Page>
                </Route>
            </Switch>
            <Switch>
                <Route path={`${url}/create`}>
                    <Dialog show={true} title={'Create product'}
                            onClose={() => push(url)}><CreateProduct></CreateProduct></Dialog>
                </Route>
                <Route path={`${url}/:productId/edit`}>
                    <Dialog show={true} title={'Edit product'} onClose={() => push(url)}><EditProduct></EditProduct></Dialog>
                </Route>
            </Switch>
        </>
    );

React router v6

You'll have to use an Outlet in your nested component;
<BrowserRouter>
   <Routes>
      <Route path="/home" element={<Home />}>
         <Route path="modal" element={<Modal />} />
      </Route>
   </Routes>
</BrowserRouter>

And inside the Modal component add an Outlet;

import { Outlet } from "react-router-dom";
export default function Modal(){
   return(
      <>
         Modal code goes here
         <Outlet />
      </>
   )
}

by changing your first route to

<Route path={`${url}*`}>
  <Page title="Products" onCreateButtonClick={gotToCreateProduct}>
    <ProductsTable></ProductsTable>
  </Page>
</Route>

your component will be displayed for every route that starts with url and by removing the Switch component you will be able to match multiple routes

Related