reed53
reed53

Reputation: 83

Is there a way to wrap some routes but not others while still having a not found page?

I am fairly new to React and react-router, so there are many things I am unfamiliar with about the library. I am trying to make a website that has a header component (as well as a few other components) that appears at all times, EXCEPT for a few specific pages. There was a way I was able to get this working, however the issue arises when dealing with a 404 not found page. The 404 pages is one of the pages I do NOT want the header component to display during, but due to the way I was displaying the header this became very difficult. The following is a simplified version of the existing code:

import { createRoot } from "react-dom/client";
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
import { StrictMode } from "react";
import ConfirmLogin from "@/components/ConfirmLogin";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
        <BrowserRouter>
          <Routes>
            <Route path="/react/login.html" element={<p> Login!</p>} />
            <Route path="/react/notFound.html" element={<p>Not found</p>} />
            <Route
              path="*"
              element={
                <ConfirmLogin>
                  <h1>Header!</h1>
                    <Routes>
                      <Route path="/react/index.html" element={<p>Index</p>} />
                      <Route path="*" element={<Navigate to="/react/notFound.html" />} />
                    </Routes>
                </ConfirmLogin>
              }
            />
          </Routes>
        </BrowserRouter>
  </StrictMode>
);

While the code works, it has a few issues that I would like to resolve:

  1. The original route that the user was trying to go to is lost. I instead direct them to notfound.html. I would prefer to keep the original link intact
  2. The user is forced to log in via the <ConfirmLogin> component (this is a custom component to just check if the user has logged in yet, and redirect to the login page if not), but then after they log in, they will then be taken to a 404 error page. I would prefer they just go straight to the error page and not be required to log in.

It would be ideal if I could do something like this:

import { createRoot } from "react-dom/client";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import { StrictMode } from "react";
import ConfirmLogin from "@/components/ConfirmLogin";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
        <BrowserRouter>
          <Routes>
            <Route path="/react/login.html" element={<p> Login!</p>} />
            <Route
              path="*"
              element={
                <Routes>
                  <ConfirmLogin>
                    <h1>Header!</h1>
                        <Route path="/react/index.html" element={<p>Index</p>} />
                  </ConfirmLogin>
                  <Route path="*" element={<p>Not found</p>} />
                </Routes>
              }
            />
          </Routes>
        </BrowserRouter>
  </StrictMode>
);

But this doesn't work, I assume because the Route components have to be direct children of the Routes component.

The only way around this I can think of is by somewhere storing a list of all valid html links and then somehow generating the routes around that list, but I would prefer to avoid storing the different paths in multiple locations.

Any help would be greatly appreciated!

Edit: I was able to get this working. I did not realize that a Route component without a path specified does not match all paths. I thought that no path was equivalent to "*". With this, you can have a Route with no path that adds the header, then have children Route components within that one like so:

import { createRoot } from "react-dom/client";
import { BrowserRouter, Outlet, Route, Routes } from "react-router-dom";
import { StrictMode } from "react";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
        <BrowserRouter>
          <Routes>
            <Route path="/react/login.html" element={<p> Login!</p>} />
            <Route path="/react/notFound.html" element={<p>Not found</p>} />
            <Route element={<><p>You are logged in!</p><Outlet></Outlet></>}>
              <Route path="/react/index.html" element={<p>This is a test</p>} />
            </Route>
            <Route path="*" element={<p>Not found</p>} />
          </Routes>
        </BrowserRouter>
  </StrictMode>
);

Allowing the 404 page to still be displayed without the header.

Upvotes: 1

Views: 17

Answers (0)

Related Questions