Nested routing react-router-dom v6 not working - javascript

I am new to React and I am following this project. But I am stuck on converting the nested routed in version6 of react-router-dom.
In V5 it is as follows:
App.js
return (
<div>
<Header />
<Switch>
<Route exact path='/' component={HomePage} />
<Route path='/shop' component={ShopPage} />
<Route exact path='/checkout' component={CheckoutPage} />
<Route
exact
path='/signin'
render={() =>
this.props.currentUser ? (
<Redirect to='/' />
) : (
<SignInAndSignUpPage />
)
}
/>
</Switch>
</div>
);
ShopPage
const ShopPage = ({ match }) => (
<div className='shop-page'>
<Route exact path={`${match.path}`} component={CollectionsOverview} />
<Route path={`${match.path}/:collectionId`} component={CollectionPage} />
</div>
);
I want to convert it in V6 and I had tried as follows:
My App.js
return (
<div >
<Header />
<Routes>
<Route path='/' element={<HomePage />} />
<Route path='/shop' element={<ShopPage />} />
<Route path='/checkout' element={<CheckoutPage />} />
<Route path='/signin' element={<>
{this.props.currentUser ?
<Navigate to="/" />
:
<SignInAndSignUpPage />
}
</>
}
/>
<Route path='/signin' element={this.props.user ? <Navigate to="/" /> : <SignInAndSignUpPage />} />
</Routes>
</div>
);
My Shopage
const ShopPage = () => {
let { pathname } = useLocation();
console.log(pathname);
return (
<div className='shop-page'>
<Routes>
<Route path={`${pathname}`} element={<CollectionsOverview />} />
<Route path={`${pathname}/:collectionId`} element={<CollectionItems />} />
</Routes>
</div>
)
};
In pathname console log I am getting /shop but the items are not showing.
How can acheive nested routing in v6?

It looks like CollectionsOverview is what is rendered exactly on "/shop". Nested routes operate a little different in v6 than they did in v5. You don't need to get the current path/url to build nested routes/links, you can just use relative routes.
Example:
const ShopPage = () => {
return (
<div className='shop-page'>
<Routes>
<Route path="/" element={<CollectionsOverview />} />
<Route path=":collectionId" element={<CollectionItems />} />
</Routes>
</div>
);
};
Optionally, you can can convert ShopPage into a layout route.
Example:
import { Outlet } from 'react-router-dom';
const ShopPage = () => (
<div className='shop-page'>
<Outlet />
</div>
);
App
return (
<div >
<Header />
<Routes>
<Route path='/' element={<HomePage />} />
<Route path='/shop' element={<ShopPage />}>
<Route index element={<CollectionsOverview />} />
<Route path=":collectionId" element={<CollectionItems />} />
</Route>
<Route path='/checkout' element={<CheckoutPage />} />
<Route
path='/signin'
element={this.props.currentUser
? <Navigate to="/" />
: <SignInAndSignUpPage />
}
/>
<Route
path='/signin'
element={this.props.user
? <Navigate to="/" />
: <SignInAndSignUpPage />
}
/>
</Routes>
</div>
);

Related

'Outlet' is not defined in react-router v6.4

How Outlet should be defined in react-router v6.4.
Here is my code
function Layout() {
return (
<div>
<Navbar />
<Outlet />
<Footer />
</div>
);
}
Import the values from the router and use the following structure
import { BrowserRouter, Routes, Route } from "react-router-dom";
<BrowserRouter>
<HeaderSignIn />
<Routes>
<Route path="/" element={<HomePageSignIn />} />
<Route path="/sign-in" element={<SigIn />} />
<Route path="/login" element={<LogIn />} />
<Route path="/admin_login" element={<Login />} />
<Route path="/explore" element={<Explore />} />
<Route path="/shop" element={<ShopView />} />
<Route path="/about" element={<About />} />
<Route path="/job" element={<PleaseLogIn />} />
<Route path="/new-shop-item" element={<PleaseLogIn />} />
<Route path="/new-shop" element={<PleaseLogIn />} />
</Routes>
<Footer />
</BrowserRouter>
Follow the ReactRouter Documentation for more information

I'm making a online tutorial website from react.js which has course and course has some sub topic .IS there any short cut for this code which I rote

In my code, there are many imports (38 import components) and routes(38 routes) so can simplify those into a few imports and routes is there any way available...???
function App() { return (
<Router>
<SideBar>
<Routes>
<Route path="/Architecture" element={<ReactJs_Architecture />} />
<Route path="/JSX" element={<ReactJs_JSX />} />
<Route path="/Components" element={<ReactJs_Components />} />
<Route path="/Styling" element={<ReactJs_Styling />} />
<Route path="/Properties" element={<ReactJs_Properties />} />
<Route path="/EventManagement" element={<ReactJs_EventManagement />} />
<Route path="/StateManagement" element={<ReactJs_StateManagement />} />
<Route path="/Redux" element={<ReactJs_Redux />} />
<Route path="/Animation" element={<ReactJs_Animation />} />
<Route path="/Home" element={<NodeJs_Home />} />
<Route path="/Node_Introduction" element={<Node_Introduction/>} />
<Route path="/EnvironmentSetup" element={<NodeJs_EnvironmentSetup />} />
<Route path="/REPLTerminal" element={<NodeJs_REPLTerminal />} />
<Route path="/PackageManager" element={<NodeJs_PackageManager />} />
<Route path="/Buffers" element={<NodeJs_Buffers />} />
<Route path="/Streams" element={<NodeJs_Streams />} />
<Route path="/WebModule" element={<NodeJs_WebModule />} />
<Route path="/ScalingApplications" element={<NodeJs_ScalingApplications />} />
<Route path="/Packaging" element={<NodeJs_Packaging />} />
<Route path="*" element= { < not found />} />
</Routes>
</SideBar>
</Router>
);
}
export default App;
If your items are long always try to create an array and list all your routes there like this
const ROUTE_PATHS = {
PRICING: "/pricing",
ACTIONS: "/actions",
};
const routeItems = [
{
name: "Pricing",
path: ROUTE_PATHS.PRICING,
Component: Pricing,
},
{
name: "Bulk Actions",
path: ROUTE_PATHS.ACTIONS,
Component: Actions,
},
];
And now add a loop to iterate over all the routes
<Routes>
{routeItems.map(item => {
const { Component } = item;
return (
<Route
key={item.name}
path={item.path}
element={
<Component />
}
/>
);
})}
</Routes>
Now it made simple.

Uncaught Error: [Topbar] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>

I have looked at the previous questions and googled for the answer and I think I almost know what the issue in here is, but don't know how to solve it.
return (
<Router>
<Routes>
<Route path="/login" element={<Login />} />
{admin && (
<>
<Topbar />
<div className="container">
<Sidebar />
<Route path="/" element={<Home />} />
<Route path="/users" element={<UserList />} />
<Route path="/user/:userId" element={<User />} />
<Route path="/newUser" element={<NewUser />} />
<Route path="/products" element={<ProductList />} />
<Route path="/product/:productId" element={<Product />} />
<Route path="/newproduct" element={<NewProduct />} />
</div>
</>
)}
</Routes>
</Router>
Please tell me how to setup the topar and slidebar components here.
Requesting my fellow coders to look at this one and thanks in advance.
The error is clear, you only can use the <Route /> tag, and remove the <div className="container"> also.
Try this:
return (
<>
<Topbar />
<Sidebar />
<Router>
<Routes>
<Route path="/login" element={<Login />} />
{admin && (
<>
<Route path="/" element={<Home />} />
<Route path="/users" element={<UserList />} />
<Route path="/user/:userId" element={<User />} />
<Route path="/newUser" element={<NewUser />} />
<Route path="/products" element={<ProductList />} />
<Route path="/product/:productId" element={<Product />} />
<Route path="/newproduct" element={<NewProduct />} />
</>
)}
</Routes>
</Router>
</>
)
Or you can import your TOPBAR and SIDEBAR components inside every other component.
to render a login page without a topbar and sidebar create a private router component and wrap it around all the routes you want to render a topbar and sidebar with
use react-outlet
here is what worked for me
app.js
import "./App.css";
import Sidebar from "./Components/Sidebar/Sidebar";
import TopBar from "./Components/TopBar/TopBar";
import Home from "./Pages/Home/Home";
import UserList from "./Pages/UserList/UserList";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import User from "./Pages/User/User";
import NewUser from "./Pages/NewUser/NewUser";
import ProductList from "./Pages/ProductList/ProductList";
import Product from "./Pages/Product/Product";
import NewProduct from "./Pages/NewProduct/NewProduct";
import { useSelector } from "react-redux";
import Login from "./Pages/Login/Login";
import { Outlet } from "react-router-dom";
const SidebarLayout = () => (
<>
<TopBar />
<div className="container">
<Sidebar />
<Outlet />
</div>
</>
);
function App() {
// const admin = useSelector((state) => state.user.currentUser.isAdmin);
const admin = JSON.parse(
JSON.parse(localStorage.getItem("persist:root")).user
).currentUser.isAdmin;
return (
<BrowserRouter>
<Routes>
<Route element={<SidebarLayout />}>
<Route index element={<Home />} />
<Route exact path="/users" element={<UserList />} />
<Route exact path="/users/:id" element={<User />} />
<Route exact path="/newUser" element={<NewUser />} />
<Route exact path="/products" element={<ProductList />} />
<Route exact path="/products/:id" element={<Product />} />
<Route exact path="/newProduct" element={<NewProduct />} />
</Route>
<Route exact path="/login" element={<Login />} />
</Routes>
</BrowserRouter>
);
}
export default App;
import React from "react";
import { Router, Routes, Route } from "react-router-dom";
import Home from "./Home";
import UserList from "./UserList";
import NewUser from "./NewUser";
import ProductList from "./ProductList";
import Product from "./Product";
import NewProduct from "./NewProduct";
import Login from "./Login";
const AppRoute = () => {
return (
<>
{admin ? (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/users" element={<UserList />} />
<Route path="/user/:userId" element={<User />} />
<Route path="/newUser" element={<NewUser />} />
<Route path="/products" element={<ProductList />} />
<Route path="/product/:productId" element={<Product />} />
<Route path="/newproduct" element={<NewProduct />} />
</Routes>
</Router>
) : (
<Router>
<Routes>
<Route path="/" element={<Login />} />
</Routes>
</Router>
)}
</>
);
};
export default AppRoute;
const admin = JSON.parse(
JSON.parse(localStorage.getItem("persist:root")).user
).currentUser.isAdmin;
return (
<Router>
<>
<Topbar />
<div className="container">
<Sidebar />
<Routes>
<Route
path="/login"
element={admin ? <Navigate to="/" /> : <Login />}
/>
<Route exact path="/" element={<Home />}></Route>
<Route path="/users" element={<UserList />}></Route>
<Route path="/user/:userId" element={<User />}></Route>
<Route path="/newUser" element={<NewUser />}></Route>
<Route path="/products" element={<ProductList />}></Route>
<Route path="/product/:productId" element={<Product />}></Route>
<Route path="/newproduct" element={<NewProduct />}></Route>
</Routes>
</div>
</>
</Router>
); ```

Detect the url (on reactjs) to hide an element on the page

On a project I just started on reactjs, I should hide an element when the url changes. I searched and did not find something useful.
I would like to hide the Sidebar when the url is not Search.
Thanks to anyone who wants to give me a hand.
import React from 'react';
import { Routes, Route } from "react-router-dom";
import 'bootstrap/dist/css/bootstrap.css';
import 'react-bootstrap';
import './App.css';
import NavBarTop from './components/layouts/header/NavBar_top';
import Sidebar from './components/layouts/Sidebar';
import Home from './components/pages/Home';
import Login from './components/pages/Login';
import Register from './components/pages/Register';
import Search from './components/pages/Search';
import E404 from './components/pages/E404';
function App() {
return (
<>
<div>
<NavBarTop />
<div className="container-fluid maincon">
<Sidebar />
<Routes>
<Route path="/" exact element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
<Route path="/search" element={<Search />} />
<Route path="*" element={<E404 />} />
</Routes>
</div>
</div>
</>
);
}
export default App;
I would like to hide the Sidebar when the url is not Search.
Just render the Sidebar only with the Search component instead of unconditionally with everything.
<div>
<NavBarTop />
<div className="container-fluid maincon">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
<Route
path="/search"
element={(
<>
<Sidebar />
<Search />
</>
)}
/>
<Route path="*" element={<E404 />} />
</Routes>
</div>
</div>
If you wanted to render Sidebar with several routes, then create a layout component. Nested/wrapped Route components are rendered into the Outlet component.
import { Outlet } from 'react-router-dom';
const SidebarLayout = () => (
<>
<Sidebar />
<Outlet />
</>
);
...
<div>
<NavBarTop />
<div className="container-fluid maincon">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
<Route element={SidebarLayout}>
<Route path="/search" element={<Search />} />
... other routes to render with sidebar ...
</Route>
<Route path="*" element={<E404 />} />
</Routes>
</div>
</div>
there are multiple ways to do that.. this is only one...
export default function Wrapper() {
const urlWindow = window.location;
console.log(urlWindow.pathname.split("/")[1]);
const acceptedPaths = ["login", "register", "search", "test"];
return (
<>
<div>
navbar
<div className="container-fluid">
<div className="row">
{acceptedPaths.includes(urlWindow.pathname.split("/")[1]) ? (
<>
<Sidebar />
<MainContent />
</>
) : "Show 404 page"}
</div>
</div>
</div>
</>
);
}
const Sidebar = () => {
return <div className="col-md-2">I'm sidebar</div>;
};
const MainContent = () => {
return <div className="col-md-10">I'm main content</div>;
};
Firstly, you need import useLocation in react-router-dom
import { Routes, Route, useLocation } from "react-router-dom";
and call it in App function to get the current URL path which is used to check against /search for hiding/showing SideBar
function App() {
const location = useLocation();
const currentPath = location.pathname
return (
<>
<div>
<NavBarTop />
<div className="container-fluid maincon">
{currentPath === '/search' && <Sidebar />}
<Routes>
<Route path="/" exact element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
<Route path="/search" element={<Search />} />
<Route path="*" element={<E404 />} />
</Routes>
</div>
</div>
</>
);
}
you can use hook named as useSearchParam
const [searchParams, setSearchParams] = useSearchParams();
to get query/url params as string.

How to go specific route without rendering some components in React?

I am using react-router-dom v6. I want my Login page to be rendered without the Sidebar and Topbar components. How to do it?
function App() {
return (
<Router>
<Container>
<Sidebar />
<Content>
<Topbar />
<MainContent>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/users" element={<UserList />} />
<Route path="/users/:id" element={<User />} />
<Route path="/newUser" element={<NewUser />} />
<Route path="/products" element={<ProductList />} />
<Route path="/products/:id" element={<Product />} />
<Route path="/newProduct" element={<NewProduct />} />
<Route path="/login" element={<Login />} />
</Routes>
</MainContent>
</Content>
</Container>
</Router>
);
}
I don't want my login page to render inside the MainContent but taking the whole page without Sidebar and Topbar.
I tried moving the Routes upper and have the login route above the sidebar but there is an error Error: [Sidebar] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>
Since SideBar and TopBar appear to be part of a "layout", and you want a different "layout" specifically for "/login" then I suggest abstracting the container components into layout components. Each layout container should render an Outlet for their respective nested routes.
const AppLayout = () => (
<Container>
<Sidebar />
<Content>
<Topbar />
<MainContent>
<Outlet />
</MainContent>
</Content>
</Container>
);
const LoginLayout = () => (
<Container>
<Content>
<MainContent>
<Outlet />
</MainContent>
</Content>
</Container>
);
...
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<AppLayout />}>
<Route index element={<Home />} />
<Route path="users" element={<UserList />} />
<Route path="users/:id" element={<User />} />
<Route path="newUser" element={<NewUser />} />
<Route path="products" element={<ProductList />} />
<Route path="products/:id" element={<Product />} />
<Route path="newProduct" element={<NewProduct />} />
</Route>
<Route path="/login" element={<LoginLayout />}>
<Route index element={<Login />} />
</Route>
</Routes>
</Router>
);
}
function App() {
return (
<Router>
<Container>
{
Login || <Sidebar />
}
<Content>
{
Login || <Topbar />
}
<MainContent>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/users" element={<UserList />} />
<Route path="/users/:id" element={<User />} />
<Route path="/newUser" element={<NewUser />} />
<Route path="/products" element={<ProductList />} />
<Route path="/products/:id" element={<Product />} />
<Route path="/newProduct" element={<NewProduct />} />
<Route path="/login" element={<Login />} />
</Routes>
</MainContent>
</Content>
</Container>
</Router>
);
}
try conditional rendering. It works for me!

Categories