Show or hide component according to the current path in React Router Dom

Viewed 81

I want to show or hide NewsLetter according to the current path. For example I want it hidden for login and register pages, i.e., (path login & register). I have tried using useLocation but it cannot be used outside of the router.

I hope to get a good solution so that I can also render navbar and footer in similar conditions too. Here is my current code inside App.js:

<BrowserRouter>
  <Wrapper>
    <Announcement />
    <Navbar />
    <Routes>
      <Route index path="/" element={<Home />}></Route>
      <Route path="/products" element={<ProductList />}></Route>
      <Route path="/products/:category" element={<ProductList category="true" />}></Route>
      <Route path="/product/:id" element={<Product />}></Route>
      <Route path="/register" element={isAuthenticated ? <Navigate replace to="/" /> : <Register />}></Route>
      <Route path="/login" element={isAuthenticated ? <Navigate replace to="/" /> : <Login />}></Route>
      <Route path="/account" element={isAuthenticated ? <Navigate replace to="/" /> : <Account />}></Route>
      <Route path="/forgot-password" element={isAuthenticated ? <Navigate replace to="/" /> : <ForgotPassword />}></Route>
      <Route path="/cart" element={<Cart />}></Route>
      <Route path="/wishlist" element={<Wishlist />}></Route>
      <Route path="/orders/tracking" element={<Tracking />}></Route>
      <Route path="/orders/checkout" element={<Checkout />}></Route>
    </Routes>
    <Newsletter />
  </Wrapper>
  <Footer />
</BrowserRouter>
3 Answers

Maybe try with nested route by using Outlet in Newsletter component

<BrowserRouter>
 <Wrapper>
   <Announcement />
   <Navbar />
   <Routes >
       <Route exact path="/" element={<Newsletter />} >
           <Route index element={<Home />}></Route>
           <Route path="products" element={<ProductList />}></Route>
           <Route path="products/:category" element={<ProductList category="true" />}></Route>
           <Route path="product/:id" element={<Product />}></Route>
           <Route path="register" element={isAuthenticated ? <Navigate replace to="/" /> : <Register />}></Route>
           <Route path="login" element={isAuthenticated ? <Navigate replace to="/" /> : <Login />}></Route>
           <Route path="account" element={isAuthenticated ? <Navigate replace to="/" /> : <Account />}></Route>
           <Route path="forgot-password" element={isAuthenticated ? <Navigate replace to="/" /> : <ForgotPassword />}></Route>
           <Route path="cart" element={<Cart />}></Route>
           <Route path="wishlist" element={<Wishlist />}></Route>
           <Route path="orders/tracking" element={<Tracking />}></Route>
           <Route path="orders/checkout" element={<Checkout />}></Route>
       </Route>
   </Routes>
 </Wrapper>
 <Footer />
</BrowserRouter>

and in Newsletter component

const Newsletter = () => {
    ... your conditions 

    return (
        <Outlet /> 
        ... newsletter content
    )
}

First solution

You could simply leave Newsletter component where it's inside BrowserRouter and change its content as below. Using useLocation either it renders its content or return an empty JSX depending on the path.

import { useLocation } from "react-router-dom";
const Newsletter = () => {
  // ...
  const { pathname } = useLocation();
  // ...
  if (pathname === "/login" || pathname === "/register") {
    return <></>;
  }
  // render actual content
  return <div></div>;
};
export default Newsletter;

Second one

Another way is to control everything in one place by creating a Layout.js commponent, like so:

import { Outlet, useLocation } from "react-router-dom";

const Layout = () => {
  const { pathname } = useLocation();
  return (
    <>
      <Announcement />
      <Navbar />
      <Outlet />
      {pathname !== "/login" && pathname !== "/register" && <Newsletter />}
    </>
  );
};

export default Layout;

Then change your routes set up as below. Notice the Layout component. Make sure to import it:

<BrowserRouter>
  <Wrapper>
    <Routes>
     <Route element={<Layout />}>
      <Route index path="/" element={<Home />}></Route>
      <Route path="/products" element={<ProductList />}></Route>
      <Route path="/products/:category" element={<ProductList category="true" />}></Route>
      <Route path="/product/:id" element={<Product />}></Route>
      <Route path="/register" element={isAuthenticated ? <Navigate replace to="/" /> : <Register />}></Route>
      <Route path="/login" element={isAuthenticated ? <Navigate replace to="/" /> : <Login />}></Route>
      <Route path="/account" element={isAuthenticated ? <Navigate replace to="/" /> : <Account />}></Route>
      <Route path="/forgot-password" element={isAuthenticated ? <Navigate replace to="/" /> : <ForgotPassword />}></Route>
      <Route path="/cart" element={<Cart />}></Route>
      <Route path="/wishlist" element={<Wishlist />}></Route>
      <Route path="/orders/tracking" element={<Tracking />}></Route>
      <Route path="/orders/checkout" element={<Checkout />}></Route>
     <Route>
    </Routes>
  </Wrapper>
  <Footer />
</BrowserRouter>

May be you are looking for this :

window.location.pathname
Related