skip to Main Content

I have Global file which holds the following routes:

global.tsx

import React from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import LoginPage from "../../pages/Authentication/Login";
import SignupPage from "../../pages/Authentication/Signup";

const Global = () => {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<LoginPage />} />
        <Route path="/signup" element={<SignupPage />}></Route>
      </Routes>
    </Router>
  );
};

export default Global;

and another file called Admin which holds these routes:

import React, { useContext, useEffect } from "react";
import "../../styles/App.scss";
import { ThemeContext } from "../../context/ThemeContext";
import { DARK_THEME, LIGHT_THEME } from "../../constants/themeConstants";
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
import MoonIcon from '../../assets/icons/moon.svg';
import SunIcon from '../../assets/icons/sun.svg';
import BaseLayout from "../../layout/BaseLayout";
import DashboardScreen from "../../screens/Dashboard/DashboardScreen";
import PageNotFound from "../../screens/error/PageNotFound";

const Admin = () => {
  const { theme, toggleTheme } = useContext(ThemeContext);

  console.log(theme);

  useEffect(() => {
    if (theme === DARK_THEME) {
      document.body.classList.add("dark-mode");
    } else {
      document.body.classList.remove("dark-mode");
    }
  }, [theme]);

  return (
    <>
    <Router>
      <Routes>
        <Route element={<BaseLayout />}>
          <Route path="/admin" element={<DashboardScreen />}></Route>
          <Route path="*" element={<PageNotFound />}></Route>
        </Route>
      </Routes>
      <button
        type="button" 
        className="theme-toggle-btn"
        onClick={toggleTheme}
      >
        <img
          src={theme === LIGHT_THEME ? SunIcon: MoonIcon}
          alt=""
          className="theme-icon"
        />
      </button>
    </Router>
    </>
  );
};

export default Admin;

and then combined them in one file:

// import "./App.scss";
import { SidebarProvider } from "./context/SidebarContext";
import { ThemeProvider } from "./context/ThemeContext";

import Admin from "./routes/admin/Admin";
import Global from "./routes/global/Global";

function App() {
  return (
    <div className="App">
      <Global />

      <ThemeProvider>
        <SidebarProvider>
          <Admin></Admin>
        </SidebarProvider>
      </ThemeProvider>
    </div>
  );
}

export default App;

what happens that is that the sidebar from the admin Router comes up with the login or sign up pages from Global component although the sidebar is from admin file in a different router as you can see in the following image:

enter image description here

I tried a lot of times with different ways to seperate them by playing with the routes but I couldn’t. There has to be a way so that the sidebar don’t come up with the the routes although the sidebar itself is a different route

2

Answers


  1. The two routers are rendered at the same time and so also render any matched routes at the same time.

    You only need one router per React application. Refactor the code so App renders the single necessary Router component, and all routes rendered under a single Routes component that handles route matching. Descendent route paths are built relative to their parent route component.

    Example:

    Update Admin to be a layout route component that renders an Outlet for its nested routes.

    import { Outlet } from 'react-router-dom';
    
    const Admin = () => {
      const { theme, toggleTheme } = useContext(ThemeContext);
    
      console.log(theme);
    
      useEffect(() => {
        if (theme === DARK_THEME) {
          document.body.classList.add("dark-mode");
        } else {
          document.body.classList.remove("dark-mode");
        }
      }, [theme]);
    
      return (
        <>
          <Outlet />
          <button
            type="button" 
            className="theme-toggle-btn"
            onClick={toggleTheme}
          >
            <img
              src={theme === LIGHT_THEME ? SunIcon : MoonIcon}
              alt=""
              className="theme-icon"
            />
          </button>
        </>
      );
    };
    
    import { BrowserRouter, Routes, Route } from 'react-router-dom';
    
    function App() {
      return (
        <div className="App">
          <BrowserRouter>
            <Routes>
              <Route path="/" element={<LoginPage />} />
              <Route path="/signup" element={<SignupPage />} />
              <Route
                element={(
                  <ThemeProvider>
                    <SidebarProvider>
                      <Admin />
                    </SidebarProvider>
                   </ThemeProvider>
                )}
              >
                <Route element={<BaseLayout />}>
                  <Route path="/admin" element={<DashboardScreen />} />
                  <Route path="*" element={<PageNotFound />} />
                </Route>
              </Route>
            </Routes>
          </BrowserRouter>
        </div>
      );
    }
    

    Code Splitting

    You could create functions that return JSX

    Example:

    import React from "react";
    import { Route } from "react-router-dom";
    import LoginPage from "../../pages/Authentication/Login";
    import SignupPage from "../../pages/Authentication/Signup";
    
    const globalRoutes = () => (
      <>
        <Route path="/" element={<LoginPage />} />
        <Route path="/signup" element={<SignupPage />} />
      </>
    );
    
    export default Global;
    
    const adminRoutes = () => (
      <Route
        element={(
          <ThemeProvider>
            <SidebarProvider>
              <Admin />
            </SidebarProvider>
          </ThemeProvider>
        )}
      >
        <Route element={<BaseLayout />}>
          <Route path="/admin" element={<DashboardScreen />} />
          <Route path="*" element={<PageNotFound />} />
        </Route>
      </Route>
    );
    
    import { BrowserRouter, Routes, Route } from 'react-router-dom';
    
    function App() {
      return (
        <div className="App">
          <BrowserRouter>
            <Routes>
              {globalRoutes()}
              {adminRoutes()}
            </Routes>
          </BrowserRouter>
        </div>
      );
    }
    

    It would be better to render the root-level routes directly where each routed component renders descendent routes (Routed components that render another Routes component and set of routes) instead. Basically each route is a sort of "namespace".

    Example:

    import React from "react";
    import { Route, Routes } from "react-router-dom";
    import LoginPage from "../../pages/Authentication/Login";
    import SignupPage from "../../pages/Authentication/Signup";
    
    const Global = () => {
      return (
        <Routes>
          <Route path="/" element={<LoginPage />} />
          <Route path="/signup" element={<SignupPage />} />
        </Routes>
      );
    };
    
    export default Global;
    
    const Admin = () => {
      const { theme, toggleTheme } = useContext(ThemeContext);
    
      console.log(theme);
    
      useEffect(() => {
        if (theme === DARK_THEME) {
          document.body.classList.add("dark-mode");
        } else {
          document.body.classList.remove("dark-mode");
        }
      }, [theme]);
    
      return (
        <>
          <Routes>
            <Route element={<BaseLayout />}>
              <Route path="/" element={<DashboardScreen />} /> // <-- "/admin"
              <Route path="*" element={<PageNotFound />} />
            </Route>
          </Routes>
          <button
            type="button" 
            className="theme-toggle-btn"
            onClick={toggleTheme}
          >
            <img
              src={theme === LIGHT_THEME ? SunIcon: MoonIcon}
              alt=""
              className="theme-icon"
            />
          </button>
        </>
      );
    };
    
    import { BrowserRouter, Routes, Route } from 'react-router-dom';
    
    function App() {
      return (
        <div className="App">
          <BrowserRouter>
            <Routes>
              <Route path="/*" element={<Global />} />
              <Route
                path="/admin/*"
                element={(
                  <ThemeProvider>
                    <SidebarProvider>
                      <Admin />
                    </SidebarProvider>
                  </ThemeProvider>
                )}
              />
            </Routes>
          </BrowserRouter>
        </div>
      );
    }
    
    Login or Signup to reply.
  2. Change your Structure based on your requirements. you can create your two different layouts for different page requirement

    Look at the below routes and structure. This will work for you

    App.js

    <Router>
        <Switch>
            {/* ***** make login page without sidebar ***** */}
            <Route exact path='/' component={LoginPage} />
            <Route exact path='/signup' component={SignupPage} />
            <Route exact path='/admin/*' component={WithSidebarPageRoute} />
            <Route path='/not-found'>
                <PageNotFound />
            </Route>
            <Redirect from='*' to='/not-found' />
        </Switch>
    </Router>;
    

    WithSidebarPageRoute.js

    <MainLayout>
        <Switch>
            <Route exact path="/admin/dashboard" component={DashboardPage}  />
            <Route exact path="/admin/page1" component={PageOne}  />
            <Route exact path="/admin/page2" component={PageTwo} />
            <Redirect from="*" to="/not-found" />
        </Switch>
    </MainLayout>
    

    MainLayout.js

    const { children } = this.props;
    return (
        <main className="cr-app bg-light">
        {/* ***** sidebar only render in admin pages ***** */}
        <Sidebar />
            <Content>
                <Header />
                {children}
            </Content>
        </main>
    );
    

    Let me know if it is helpful.

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