1

I have multiple pages that have the navbar and the sidebar as component in my app.js and I have another page such as my login page that does not have this navbar and sidebar. How do I make the routing using react-router so that the login page will be entirely a different route page without the sidebar and navbar, while the other multiple pages will have the sidebar and navbar on the app.js?

Below is what I have done so far but the dashboard page inside the route is not displaying.

app.js

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/login" element={<Login />} />
        <Route path='/' element={(
          <>
            <Container>
              <SideBar />
              <Main>
                <Navbar />
                <Wrapper>
                  <Route path='landing' element={<Dashboard/>} />
                  <Route path='pricing' element={<Price/>} />
                </Wrapper>
              </Main>
            </Container>
          </>
        )}/>  
      </Routes>
    </Router>
  );
}

export default App;

Right now the whole page is not working again. I am currently getting the is error message:

Uncaught runtime errors:
×
ERROR
A <Route> is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your <Route> in a <Routes>.
    at invariant (http://localhost:3000/static/js/bundle.js:17236:11)
    at Route (http://localhost:3000/static/js/bundle.js:66637:78)
    at renderWithHooks (http://localhost:3000/static/js/bundle.js:51633:22)
    at mountIndeterminateComponent (http://localhost:3000/static/js/bundle.js:54919:17)
    at beginWork (http://localhost:3000/static/js/bundle.js:56215:20)
    at HTMLUnknownElement.callCallback (http://localhost:3000/static/js/bundle.js:41225:18)
    at Object.invokeGuardedCallbackDev (http://localhost:3000/static/js/bundle.js:41269:20)
    at invokeGuardedCallback (http://localhost:3000/static/js/bundle.js:41326:35)
    at beginWork$1 (http://localhost:3000/static/js/bundle.js:61200:11)
    at performUnitOfWork (http://localhost:3000/static/js/bundle.js:60447:16)

Is there a better approach to this?

Drew Reese
  • 165,259
  • 14
  • 153
  • 181

2 Answers2

1

Issue

The issue is that you are trying to render descendent routes that are not wrapped in a Routes component.

Solution w/ Descendent Routes

Wrap the descendent routes in the Routes component and ensure the parent route appends the "*" wildcard matcher to the end of its path so all descendent routes can also be matched and rendered.

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/login" element={<Login />} />
        <Route
          path="/*"
          element={(
            <Container>
              <SideBar />
              <Main>
                <Navbar />
                <Wrapper>
                  <Routes>
                    <Route path='landing' element={<Dashboard />} />
                    <Route path='pricing' element={<Price/>} />
                  </Routes>
                </Wrapper>
              </Main>
            </Container>
          )} 
        />  
      </Routes>
    </Router>
  );
}

export default App;

Solution w/ Nested Routes

You could alternatively create a layout route component that renders an Outlet for nested routes to render their content into.

Example:

import {
  BrowserRouter as Router,
  Routes,
  Route,
  Outlet
} from 'react-router-dom';

const Layout = () => (
  <Container>
    <SideBar />
    <Main>
      <Navbar />
      <Wrapper>
        <Outlet />
      </Wrapper>
    </Main>
  </Container>
);

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/login" element={<Login />} />
        <Route path="/" element={<Layout />}>
          <Route path='landing' element={<Dashboard />} />
          <Route path='pricing' element={<Price/>} />
        </Route>
      </Routes>
    </Router>
  );
}

export default App;
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
-1

In your code, you need to add a forward slash (/) before the landing and pricing paths in the Route components to make them absolute paths. Otherwise, they will be considered relative to the current path and won't match properly.

Here the corrected code for your App.js:

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/login" element={<Login />} />
        <Route
          path="/"
          element={
            <>
              <Container>
                <SideBar />
                <Main>
                  <Navbar />
                  <Wrapper>
                    <Route path="/landing" element={<Dashboard />} />
                    <Route path="/pricing" element={<Price />} />
                  </Wrapper>
                </Main>
              </Container>
            </>
          }
        />
      </Routes>
    </Router>
  );
}

export default App;

With this change, the routes for the landing and pricing pages should now work correctly, and the corresponding components (Dashboard and Price) will be displayed inside the Wrapper component, which includes the common sidebar and navbar components. Remember to make sure that the Dashboard and Price components are correctly imported into App.js

Saad Ali
  • 32
  • 4
  • i have tried adding the slash but it didn't work earlier.. currently i just noticed that the whole page is not work, i dont know if i have made a mistake somewhere but this is the error am currently having: ``` is only ever to be used as the child of element, never rendered directly. Please wrap your in a .``` – Stanley Omeje Aug 03 '23 at 07:48