skip to Main Content

I want the header to be rendered when on the home page when the user navigates to "/content", and when they navigate to "/content/about", the About page is rendered without a header. This does not happen. Can you tell me where my problem is?

"/content":
Header
Home page by header

"/content/about":
About page without header

App.js:

import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import Content from "./Content";

const ByHeader = () => {
  return (
    <>
      <div>Header</div>
      <Content />
    </>
  );
};

export default function App() {
  return (
    <Router>
      <Switch>
        <Route path="/content">
          <ByHeader />
        </Route>
        <Route path="/content/*">
          <Content />
        </Route>
      </Switch>
    </Router>
  );
}

and

import React from "react";
import { Route } from "react-router-dom";

const Home = () => {
  return <div>Home page by header</div>;
};

const About = () => {
  return <div>About page without header</div>;
};

const Content = () => {
  return (
    <>
      <Route path="/" exact>
        <Home />
      </Route>
      <Route path="/about" exact>
        <About />
      </Route>
    </>
  );
};

export default Content;

cosesandbox

2

Answers


  1. Router.js

    const PrivateRoute = ({ children }) => {
      const navigate = useNavigate();
    
      React.useEffect(() => {
        // here you should have IsAuthorized in your services 
        // to check if user is authorized or not
        if (!IsAuthorized) {
          navigate('/image');
        }
      }, []);
    
      return children;
    };
    
    const Image =()=> {
      return (
        <div>
          <header> your header goes here </header>
          <div>Image page</div>
        </div>
      )
    }
    
    const ImageAbout =()=> {
      return (
        <div>
          <header> don't include header </header>
          <div>Image page</div>
        </div>
      )
    }
    
    export const  RootRouter = () => {
    
    return (
        <Routes>
          <Route
            path="/"
            element={
              <PrivateRoute>
                <RootPage />
              </PrivateRoute>
            }
          >
            <Route path="/image/about" element={<Image/>} />
            <Route path="/image/about" element={<ImageAbout />} />
        </Route>
        </Routes>
    }
    

    Usage

    ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
      <React.StrictMode>
        <BrowserRouter>
          <RootRouter />
        </BrowserRouter>
      </React.StrictMode>
    );
    
    Login or Signup to reply.
  2. Issue

    The code isn’t working right now for a few reasons:

    1. You are rendering all the routes, including the route that renders the header, into a single Switch component.
    2. The route in the Switch that renders the header is listed first and once matched, the rest of the routes are ignored, matching or not.
    3. The Content component is using absolute paths that don’t include the "content" path segment from the parent route, so these routes are unmatchable.

    Suggested Solution

    My suggestion would be to treat the content component more as a layout component that unconditionally renders the header on a route, and renders the route content conditionally within a Switch component.

    Remember that all Route components alone are inclusively matched and rendered, e.g. anything that matches will be rendered, while Route components rendered within the Switch component are exclusively matched and rendered, e.g. the first matching Route or Redirect is rendered.

    Also keep in mind that when using the Switch or passing an array of paths to the Route component that path order and specificity matters. Order the routes/paths in the inverse order of path specificity. For example, "/content/about" is more specific than "/content" is more specific than "/", so this should be the order of the path when attempting to match.

    Here’s the implementation of my suggestion.

    Example:

    const Content = () => {
      const { path } = useRouteMatch();
      return (
        <>
          <Route path={[path]} exact component={Header} />
          <Switch>
            <Route path={`${path}/about`} component={About} />
            <Route path={path} component={Home} />
          </Switch>
        </>
      );
    };
    

    The parent/App component

    <Route path="/content" component={Content} />
    

    Demo

    Edit how-to-implement-nested-routing-by-react-router

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search