Search code examples
javascriptreactjsreact-routerreact-router-dom

How to use route between 3 components?


I have my application designed as: App.js containing two route:

  1. Login & Signup
  2. HomePage.

HomePage has the layout as: Header Sidebar ContentArea

The header and sidebar component are imported into home.

Now what I want is when I click of any entries of sidebar, I want its content to be loaded in the content area section.

I have tried using link of react router in sidebar and then route on homepage with link to each menu pages or components but that didn't work.

This is my App.js

function App() {
  return (
    <div className="App">
      <Routes>
        <Route path="/" element={<LoginSignup />} />
        <Route path="/home" element={<Home />} />
      </Routes>
    </div>
  );
}

This is my header:

const Header = () => {
  return (
    <div className='header-container'>
      <div className='header-wrapper'>
        <div className='header-content'>
          <div className='intro-bar'>
            <h3>SideMenu Name</h3>
            <h2>Welcome, User!</h2>
          </div>
          <hr></hr>
        </div>
      </div>
    </div>
  )
}

This is my sidebar:

const Sidebar = () => {
  const handleLogout = () => {
    navigate('/');
  }

  return (
    <div className='sidebar-content-menu'>
      <ul className='menu-list'>
        <div>
          <li>Item1</li>
          <li>Item2</li>
          <li>Item3</li>
        </div>
        <div>
          <li onClick={handleLogout}>Logout</li>
        </div>
      </ul>
    </div>
  )
}

And this is my home:

const Home = () => {
  const navigate = useNavigate();

  const handleLogout = () => {
    navigate('/');
  }

  return (
    <div className='home-container'>
      <div className='home-wrapper'>
        <div className='home-content'>
          <div className='home-content-side-menu-holder'>
            <h1>ZERO</h1>
            <div className='sidebar-content-menu'>
              <Sidebar />
            </div>
          </div>
          <div className='home-content-menu-content-section'>
            <Header />
            <div className='side-menu-content-section'>
              <div className='side-menu-content-viewer'>
               //i want my sidemenu links page to be displayed here.
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}

For now, I have removed

<Routes>
  <Route path="/home/item1" element={<Item1 />} />
  <Route path="/home/item2" element={<Item2 />} />
  <Route path="/home/item3" element={<Item3 />} />
</Routes>

from sidebar as resulted in errors.


Solution

  • Issue

    The issue is that the Home component is rendered on a route path that doesn't allow for descendent routes to be rendered.

    Solution

    Using Descendent Routes

    Append the wildcard "*" matcher to the end of the home page path so that descendent routes can also be matched and rendered.

    Example:

    App

    export default function App() {
      return (
        <div className="App">
          <Routes>
            <Route path="/" element={<LoginSignup />} />
            <Route path="/home/*" element={<Home />} />
          </Routes>
        </div>
      );
    }
    

    Descendent routes build relative to their parent route, so remove the "/home" "prefix" on the descendent routes.

    Home

    const Home = () => {
      const navigate = useNavigate();
    
      const handleLogout = () => {
        navigate("/");
      };
    
      return (
        <div className="home-container">
          <div className="home-wrapper">
            <div className="home-content">
              <div className="home-content-side-menu-holder">
                <h1>ZERO</h1>
                <div className="sidebar-content-menu">
                  <Sidebar />
                </div>
              </div>
              <div className="home-content-menu-content-section">
                <Header />
                <div className="side-menu-content-section">
                  <div className="side-menu-content-viewer">
                    <Routes>
                      <Route path="/item1" element={<Item1 />} />
                      <Route path="/item2" element={<Item2 />} />
                      <Route path="/item3" element={<Item3 />} />
                    </Routes>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      );
    };
    

    enter image description here

    Using Nested Routes

    Another way would be to render an Outlet where you want the sidebar routes to render, and render them as nested routes under "/home".

    App

    export default function App() {
      return (
        <div className="App">
          <Routes>
            <Route path="/" element={<LoginSignup />} />
            <Route path="/home" element={<Home />}>
              <Route path="item1" element={<Item1 />} />
              <Route path="item2" element={<Item2 />} />
              <Route path="item3" element={<Item3 />} />
            </Route>
          </Routes>
        </div>
      );
    }
    

    Home

    import { Outlet } from 'react-router-dom';
    
    const Home = () => {
      const navigate = useNavigate();
    
      const handleLogout = () => {
        navigate("/");
      };
    
      return (
        <div className="home-container">
          <div className="home-wrapper">
            <div className="home-content">
              <div className="home-content-side-menu-holder">
                <h1>ZERO</h1>
                <div className="sidebar-content-menu">
                  <Sidebar />
                </div>
              </div>
              <div className="home-content-menu-content-section">
                <Header />
                <div className="side-menu-content-section">
                  <div className="side-menu-content-viewer">
                    <Outlet />
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      );
    };
    

    enter image description here