javascript - React Router, hide Nav & footer on certain pages. with Router V6 - Stack Overflow

So i have tried for quiet some time to hide the nav and footer ponents in certain pages of the site, bu

So i have tried for quiet some time to hide the nav and footer ponents in certain pages of the site, but sadly no luck. I've tried multiple solutions on Stackoverflow, only one of them worked partially by creating a new Layout ponent and then putting that inside the Routes to then exclude the footer and nav from for example the login page. But the issue was that it worked, but on homepage it then only showed the footer and nav, and nothing in between like the design I made in the homepage.

The only solution that works for me is by creating the and like I did in the example, but then I cant exclude certain pages and hide them there...

This is how it looks currently and not working:

import React from "react";
import Home from ".//Pages/Home";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Dashboard from "./Pages/Dashboard";
import Login from "./Pages/Login";
import Price from "./Pages/Price";
import ErrorPage from "./Pages/ErrorPage";
import Navbar from "./ponents/Navbar";
import Footer from "./ponents/Footer";
import Profile from "./Pages/Profile";

function App() {
  return (
    <Router>
      <nav>
        <Navbar />
      </nav>

      <Routes>
        <Route index element={<Home />} />
        <Route path="/Dashboard" element={<Dashboard />} />
        <Route path="/Login" element={<Login />} />
        <Route path="/Price" element={<Price />} />
        <Route path="/Profile/:username" element={<Profile />} />

        <Route path="/*" element={<ErrorPage />} />
      </Routes>

      <footer>
        <Footer />
      </footer>
    </Router>
  );
}

export default App;

So i have tried for quiet some time to hide the nav and footer ponents in certain pages of the site, but sadly no luck. I've tried multiple solutions on Stackoverflow, only one of them worked partially by creating a new Layout ponent and then putting that inside the Routes to then exclude the footer and nav from for example the login page. But the issue was that it worked, but on homepage it then only showed the footer and nav, and nothing in between like the design I made in the homepage.

The only solution that works for me is by creating the and like I did in the example, but then I cant exclude certain pages and hide them there...

This is how it looks currently and not working:

import React from "react";
import Home from ".//Pages/Home";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Dashboard from "./Pages/Dashboard";
import Login from "./Pages/Login";
import Price from "./Pages/Price";
import ErrorPage from "./Pages/ErrorPage";
import Navbar from "./ponents/Navbar";
import Footer from "./ponents/Footer";
import Profile from "./Pages/Profile";

function App() {
  return (
    <Router>
      <nav>
        <Navbar />
      </nav>

      <Routes>
        <Route index element={<Home />} />
        <Route path="/Dashboard" element={<Dashboard />} />
        <Route path="/Login" element={<Login />} />
        <Route path="/Price" element={<Price />} />
        <Route path="/Profile/:username" element={<Profile />} />

        <Route path="/*" element={<ErrorPage />} />
      </Routes>

      <footer>
        <Footer />
      </footer>
    </Router>
  );
}

export default App;
Share Improve this question asked Mar 11, 2022 at 21:05 Sermad NaJarSermad NaJar 1651 gold badge5 silver badges18 bronze badges 1
  • Where are you trying to conditionally render the navbar and footer in your code example? – Drew Reese Commented Mar 11, 2022 at 21:25
Add a ment  | 

7 Answers 7

Reset to default 5

Hi you can do it by having a state that only when the state is true the nav and footer will render:

function App() {

  const [showNav, setShowNav- = useState(true);

  return (
    <Router>
   {   showNav &&
          <nav>
            <Navbar />
          </nav>
   } 
      <Routes>
        <Route index element={<Home />} />
        <Route path="/Dashboard" element={<Dashboard />} />
        <Route path="/Login" element={<Login />} />
        <Route path="/Price" element={<Price />} />
        <Route path="/Profile/:username" element={<Profile />} />

        <Route path="/*" element={<ErrorPage />} />
      </Routes>

    {showNav &&
          <footer>
            <Footer />
          </footer>
        </Router>

    }
  );
}

And for example, if you don't want to show the nav in the homepage you will pass the setShowNav function as a prop and will set it to false:

<Route index element={<Home funcNav={setShowNav}/>} />

in home page:

props.funcNav(false);

You can use modularization in your app segmenting it into different sections. This can best be acplished by using nested routes in your app each. For example you could have example./routes/xxx have one layout and have example./other/xxx have another layout... You could also use this to optionally render the navbar and footer as you have mentioned.

It is a good idea to segment your app if it has very different features/areas where different navbar/footer binations need to be used. Here is an example using most of your code which would segment it into a main layout, and no layout.

App.js

import React from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import PageWithoutHeaderOrFooter from "./Pages/NoHeaderOrFooter";
import MainLayoutRoutes from "./Layouts/MainLayoutRoutes";

function App() {
    return (
        <Router>
            <Routes>
                <Route path="/noheaderorfooter" element={<PageWithoutHeaderOrFooter />} />
                <Route path="*" element={<MainLayoutRoutes />} />
            </Routes>
        </Router>
    );
}

export default App;

MainLayuotRoutes.js

import React from 'react';
import Home from ".//Pages/Home";
import Dashboard from "./Pages/Dashboard";
import Login from "./Pages/Login";
import Price from "./Pages/Price";
import ErrorPage from "./Pages/ErrorPage";
import Navbar from "./ponents/Navbar";
import Footer from "./ponents/Footer";
import Profile from "./Pages/Profile";
function MainLayoutRoutes() {
    return (
        <React.Fragment />
            <nav>
                <Navbar />
            </nav>{/*This is outside the routes ponent on purpose read below*/}
            <Routes>
                <Route index element={<Home />} />
                <Route path="/Dashboard" element={<Dashboard />} />
                <Route path="/Login" element={<Login />} />
                <Route path="/Price" element={<Price />} />
                <Route path="/Profile/:username" element={<Profile />} />
                <Route path="/*" element={<ErrorPage />} />
            </Routes>
            <footer>
                <Footer />
            </footer>
        <React.Fragment />
    )
}

export default MainLayoutRoutes;

A couple things I would like to note about this code.
First each child ponent in a Routes ponent must be a Route ponent (this doesn't include the element part of the Route ponent). This is why I am using a React.Fragment (you could have just as easily used <></>) if you didn't want an additional div rendered.
Secondly using this type of routing is good for segmenting your app into areas... Using areas not only is better for routing it is also better for SEO (where applicable as some crawlers don't yet support JavaScript).
Lastly I would like to mention if there is a rare case where there is only 1 page that you want a different navbar or footer, just use conditional rendering to take care of the edge case.

You can also use UseLocation from react-router-dom

const { pathname } = useLocation();
      <footer>
         {pathname !== '/<SOME_ROUTE>' &&
        <Footer />}
      </footer>

yes you should apply condition that will check if current location will display nav or not You should use useLocation from react-router To do this

Here is example from official documentation how you can do that.

Using Route ponents:

<Routes>
  <Route path="/" element={<App />}>
    <Route index element={<Home />} />
    <Route path="teams" element={<Teams />}>
      <Route path=":teamId" element={<Team />} />
      <Route path=":teamId/edit" element={<EditTeam />} />
      <Route path="new" element={<NewTeamForm />} />
      <Route index element={<LeagueStandings />} />
    </Route>
  </Route>
  <Route element={<PageLayout />}>
    <Route path="/privacy" element={<Privacy />} />
    <Route path="/tos" element={<Tos />} />
  </Route>
  <Route path="contact-us" element={<Contact />} />
</Routes>

Using useRoutes hook:

let routes = [
  {
    element: <App />,
    path: "/",
    children: [
      {
        index: true,
        element: <Home />,
      },
      {
        path: "teams",
        element: <Teams />,
        children: [
          {
            index: true,
            element: <LeagueStandings />,
          },
          {
            path: ":teamId",
            element: <Team />,
          },
          {
            path: ":teamId/edit",
            element: <EditTeam />,
          },
          {
            path: "new",
            element: <NewTeamForm />,
          },
        ],
      },
    ],
  },
  {
    element: <PageLayout />,
    children: [
      {
        element: <Privacy />,
        path: "/privacy",
      },
      {
        element: <Tos />,
        path: "/tos",
      },
    ],
  },
  {
    element: <Contact />,
    path: "/contact-us",
  },
];

And of course you should use <Outlet/> ponent inside <App /> and <PageLayout /> to render childrens inside those layouts.

App.js

<Router>
   <Routes> 
       //your other route                   
       <Route path="/404" element={<NotFound />} />
       <Route path="*" element={<Navigate to="/404" />} />
   </Routes>
</Router>

Navbar.js

const withouSidebarRoutes = ["404", "/signin", "/etc"];

const { pathname } = useLocation();
if (withouSidebarRoutes.some((item) => pathname.includes(item)))
  return null;

Work fine for me :))

What I did was to simply have a useContext for the entire application.

<HashRouter>
   <FooterContext.Provider value={{showFooter, setShowFooter}}>
      <ToastContainer theme="dark" />
      <Routes>
        <Route path="/leaderboard" element={<LeaderBoard />} />
        <Route path="/" element={<Home />} />
      </Routes>
      <Footer />
   </FooterContext.Provider>
</HashRouter>

And then use the context on my footer ponent.

function Footer() {

  const context = useContext(FooterContext)
  return (
    <footer className={`${context.showFooter ? 'block': 'hidden'}`}>
      //Your Content
    </footer>
  );
}

And finally in the ponent or page I don't wanna show my footer on i set the showFooter state to false.

This isn't too bad of an approach and its kinda flexible if you wanna change the visibilty on different pages.

Anyways I'm a noob so still may not be the best way.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1741355520a4342401.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信