Description - I made a Route.tsx
file where I would be storing all of my routes, into the app, including the App.tsx
(at path: '/') itself.
Here's my Route.tsx
file - also (Approach 1)
import { lazy } from "react";
import { createBrowserRouter, Navigate, RouteObject } from "react-router-dom";
import App from "../layout/App";
// react - lazy paint
const Home = lazy(() => import("../pages/home/Home"));
const Toys = lazy(() => import("../pages/products/Toys"));
const Books = lazy(() => import("../pages/learning/Learning"));
const NotFound = lazy(() => import("../pages/notFound/NotFound"));
export const routes : RouteObject[] = [
{
path: '/',
element: <App />,
children: [
{ path: "toys", element: <Toys /> },
{ path: "/", element: <Home /> },
{ path: "books", element: <Books /> },
{ path: "not-found", element: <NotFound /> },
{ path: "*", element: <Navigate replace to = {"/not-found"} /> }
]
}
];
// export all routes
export const router = createBrowserRouter(routes);
These all above mentioned routes are meant to wrapped inside of a container (from Material UI). Whilst, there is one page, which I wish not to enclose into the container, named Cars.tsx
, so I modified my App.tsx
file like the one mentioned below:
App.tsx file
import { Container, CssBaseline, ThemeProvider } from "@mui/material";
import { Fragment, lazy, Suspense } from "react";
import { Outlet, Route, Routes } from "react-router-dom";
import AppLoad from "./AppLoad";
import Header from "./Header";
// react - lazy imports
const Cars = lazy(() => import("../pages/cars"));
function App() {
return (
<Fragment>
<ThemeProvider theme={theme}>
<CssBaseline />
<Header />
// for lazy paint load ...
<Suspense fallback={<AppLoad message={'Please wait. Loading ...'} />}>
<Routes>
<Route path="cars" element={<Cars />} />
// this particular page, I don't want to enclose it into
// the container, because it contains a hero image.
</Routes>
<Container maxWidth={'xl'}>
<Outlet /> // all the rest of pages are inside of container
</Container>
</Suspense>
</ThemeProvider>
</Fragment>
);
}
export default App;
Problem Description - Everything is working fine, only problem I am facing is when I am at "/cars"
page, at the very bottom of the page, it is also rendering "Not-Found"
(previously it was solved by <Switch />
in react-router-dom
's version < 6).
Expected Behavior - I don't want to see "Not Found"
message at the very bottom of "Cars" page. How to fix it?
I know, the fix would be very simple, but I couldn't figure it out.
Also, I would like to ask whether or not the above mentioned approach is better (like creating a separate file for Route
, and then using it as <Outlet />
), or the traditional approach is better where we have as.
Approach 2
<Routes>
<Route path='page1' element={<Page1 />} />
<Route path='page2' element={<Page2 />} />
<Route path='page1' element={<Page3 />} />
</Routes>
Would it be going to make any difference into the First content-ful paint loading of any routed page so far if I work with any of the approach as mentioned above?
The issue it seems is that the App
component is rendering both an Outlet
for nested routes and a Routes
component for the "/cars"
descendent route. When the path is "/cars"
the App
component is rendered and renders the matching "/cars"
descendent route is rendered, but there is no matching nested "/cars"
route so it looks like the NotFound
route/component is additionally rendered in the Outlet
.
If the goal is to not render the "/cars"
route and Cars
component inside the Container
then I'd recommend creating an additional layout route and conditionally render the nested routes into the appropriate layout routes.
Example:
import { Container } from "@mui/material";
import { Outlet } from 'react-router-dom';
const ContainerLayout = () => (
<Container maxWidth="xl">
<Outlet />
</Container>
);
routes.tsx
import { lazy } from "react";
import { createBrowserRouter, Navigate, RouteObject } from "react-router-dom";
import App from "../layout/App";
// react - lazy paint
const Home = lazy(() => import("../pages/home/Home"));
const Toys = lazy(() => import("../pages/products/Toys"));
const Books = lazy(() => import("../pages/learning/Learning"));
const NotFound = lazy(() => import("../pages/notFound/NotFound"));
const Cars = lazy(() => import("../pages/cars"));
export const routes : RouteObject[] = [
{
path: '/',
element: <App />,
children: [
{
element: <ContainerLayout />,
children: [
{ index: true, element: <Home /> },
{ path: "toys", element: <Toys /> },
{ path: "books", element: <Books /> },
{ path: "not-found", element: <NotFound /> }
],
},
{ path: "cars" element: <Cars /> },
{ path: "*", element: <Navigate replace to="/not-found" /> }
]
},
];
// export all routes
export const router = createBrowserRouter(routes);
App.tsx
import { CssBaseline, ThemeProvider } from "@mui/material";
import { Suspense } from "react";
import { Outlet } from "react-router-dom";
import AppLoad from "./AppLoad";
import Header from "./Header";
function App() {
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<Header />
// for lazy paint load ...
<Suspense fallback={<AppLoad message="Please wait. Loading ..." />}>
<Outlet />
</Suspense>
</ThemeProvider>
);
}
export default App;