Nested route doesn't render component - javascript

I have a component that needs to be rendered under the Home page component. Now I have nested, but the component is not rendered. Although if you do without nesting, then everything works. How can I do this?
export default function App() {
return (
<div className="App">
<Routes>
<Route path="/" element={<Home />}>
<Route path="route1" element={<Route1 />} />
</Route>
</Routes>
</div>
);
}
export default function Route1() {
return (
<>
<h2>Route1</h2>
<Outlet />
</>
);
}
export default function Home() {
return (
<>
<h1>Home Page</h1>
</>
);
}

The Home component is rendered as a Layout Route so it should render an Outlet component for the nested routes.
export default function App() {
return (
<div className="App">
<Routes>
<Route path="/" element={<Home />}> // <-- Layout route
<Route path="route1" element={<Route1 />} /> // <-- Nested route
</Route>
</Routes>
</div>
);
}
export default function Home() {
return (
<>
<h1>Home Page</h1>
<Outlet /> // <-- Nested routes render element here
</>
);
}
Route1 only needs to render an Outlet if it is also a layout route. The Outlet can be removed if this is not the case.
export default function Route1() {
return (
<>
<h2>Route1</h2>
</>
);
}

Try wrapping your Routes with Router
Link to my stackblitz and play with it..
Also, a quick read >> https://dev.to/tywenk/how-to-use-nested-routes-in-react-router-6-4jhd
import * as React from 'react';
import {
BrowserRouter as Router,
Route,
Routes,
Link,
Outlet,
} from 'react-router-dom';
export default function App() {
return (
<div className="App">
<Router>
<nav>
<Link to="/">Home</Link> <Link to="route1">Route 1</Link>
</nav>
<Routes>
<Route path="/" element={<Home />}>
<Route path="route1" element={<Route1 />} />
</Route>
</Routes>
</Router>
</div>
);
}
function Route1() {
return <h1>"In Route 1"</h1>;
}
function Home() {
return (
<React.Fragment>
<h1>"In Home"</h1>
<Outlet />
</React.Fragment>
);
}
Using <nav> is optional.. added just for demo.. you can use your own method for routing actions (using links, buttons, etc.)

Related

nested path dosent work in react router dom

I am trying to create a browser router for my app but the nested paths are not working.
import React from 'react';
import './App.css';
import HomeScreen from './screens/HomeScreen';
import {
createBrowserRouter,
createRoutesFromElements,
Route,
RouterProvider
} from 'react-router-dom';
import LoginScreen from './screens/LoginScreen';
const router = createBrowserRouter(
createRoutesFromElements(
<Route path="/" element={<HomeScreen />}>
<Route path="dashboard" element={<LoginScreen />} />
{/* ... etc. */}
</Route>
)
);
function App() {
return (
<div className="App">
<RouterProvider router={router} />
</div>
);
}
export default App;
On this code both "localhost:3000/" and "localhost:3000/dashboard" are opening the HomeScreen page only.
Can you tell me what I should do to make "/dashboard" open LoginSrceen instead of HomeScreen?
If you are nesting routes then the parent route necessarily needs to render an Outlet component for nested routes to render their element content into.
Example:
import { Outlet } from 'react-router-dom';
const HomeScreen = () => {
...
return (
... Home screen UI ...
<Outlet /> // <-- nested routes render content here
...
);
};
const router = createBrowserRouter(
createRoutesFromElements(
<Route path="/" element={<HomeScreen />}>
<Route path="dashboard" element={<LoginScreen />} />
{/* ... etc. */}
</Route>
)
);
function App() {
return (
<div className="App">
<RouterProvider router={router} />
</div>
);
}
On the off-hand chance that you actually want HomeScreen and LoginScreen to render each on their own discrete routes, then they should not be nested one in the other, but instead should be rendered as sibling routes. Render HomeScreen on an index route such that it will be rendered when the URL path matches the parent route, e.g. "/".
const router = createBrowserRouter(
createRoutesFromElements(
<Route path="/">
<Route index element={<HomeScreen />} />
<Route path="dashboard" element={<LoginScreen />} />
{/* ... etc. */}
</Route>
)
);
function App() {
return (
<div className="App">
<RouterProvider router={router} />
</div>
);
}

React router is showing No Router matched

App.js
import Login from './Auth/components/login/Login';
import { Route, BrowserRouter, Routes, Outlet } from 'react-router-dom';
import SignIn from './Auth/components/signin/Signin';
import Home from './Home/Home';
import Dogs from './pets/Dogs';
import Cats from './pets/Cats';
import Others from './pets/Others';
import Pets from './pets/Pets';
import { Header } from './ui/Header/Header';
import { ContextClickValue } from './context/ContextClick';
import Cart from './Auth/components/cart/Cart';
function App() {
return (
<>
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} >
</Route>
</Routes>
<Header />
<Routes>
<Route path="/login" element={<Login />}></Route>
<Route path="/signin" element={<SignIn />}></Route>
<Route path="/cart" element={<Cart />}></Route>
<Route path="pets" element={< Outlet />}>
<Route index element={<Pets />} />
<Route path="dogs" element={<Dogs />} />
<Route path="cats" element={<Cats />} />
<Route path="others" element={<Others />} />
</Route>
</Routes>
</BrowserRouter>
</>
);
}
export default App;
Header.js
import { menuItems } from "../../Home/MenuItems";
import MenuItemComponent from "./MenuItemComponent";
import HeaderStyles from "./Header.module.css";
import { ContextClick, ContextClickValue } from "../../context/ContextClick";
import AddShoppingCartIcon from '#mui/icons-material/AddShoppingCart';
import {useSelector} from 'react-redux'
import { NavLink, useNavigate } from "react-router-dom";
export function Header() {
const cart = useSelector(state => state.cart.cart)
const navigate = useNavigate()
function navigateToCart(e){
e.preventDefault()
navigate('/cart')
}
let total = 0;
return (
<section className={HeaderStyles.navbar}>
<header>
<h4 className={HeaderStyles.logo}>PETSHOP</h4>
<nav>
<MenuItemComponent items={menuItems} />
</nav>
</header>
<section style={{ float:'right',margin:30, color:'white'}}>
<AddShoppingCartIcon style={{cursor:'pointer'}} onClick={navigateToCart}/>
{cart.forEach(item => {
total += item.quantity
})}
<span>{total}</span>
</section>
</section>
)
}
i have tried using Navlink also
<NavLink to="/cart">
<AddShoppingCartIcon style={{cursor:'pointer'}} />
{cart.forEach(item => {
total += item.quantity
})}
</NavLink>
I am trying to to navigate to cart (i don't know why it is not working)
In dev Tools it is showing to matching Router (i tried clearing cache and hard reload and restarted my server)
I have replaced cart to login for checking it is Navigation Successfully
sandBox link
https://codesandbox.io/p/github/muthyalaDivyaVenkatesh/authentication/master
Can Anyone let me know Why it is Not Working .
Issues
You are rendering 2 Header components, one inside the Home component within a Routes component, and another outside the routes on it's own. The Header renders links, one of which targets "/cart", but the Routes component isn't rendering a route for that path. The other Routes component is missing a route rendering on path "/".
Additionally, the Cart component isn't returning mapped JSX for the cart data selected from state.
function Cart() {
const cart = useSelector((state)=> state.cart.cart)
return (
<div>
{cart.map(cartItem => {
<ShoppingCard // <-- not returned!!
imageUrl={cartItem.imageUrl}
price={cartItem.price}
/>
})}
</div>
)
}
Solution
Create a layout component that renders the Header component, and remove the Header from the Home component.
App.js
const AppLayout = () => (
<>
<Header />
<Outlet />
</>
);
function App() {
return (
<>
<BrowserRouter>
<Routes>
<Route element={<AppLayout />}>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/signin" element={<SignIn />} />
<Route path="/cart" element={<Cart />} />
<Route path="pets">
<Route index element={<Pets />} />
<Route path="dogs" element={<Dogs />} />
<Route path="cats" element={<Cats />} />
<Route path="others" element={<Others />} />
</Route>
</Route>
</Routes>
</BrowserRouter>
</>
);
}
Home.js
export default function Home() {
return (
<>
<ImageChanging />
<TopDeals />
</>
);
}
Cart.js
function Cart() {
const cart = useSelector((state) => state.cart.cart);
return (
<div>
<h1>Cart</h1>
{cart.map((cartItem) => {
return ( // <-- return the ShoppingCard component
<ShoppingCard
width={300}
height={300}
{...cartItem}
/>
);
})}
</div>
);
}

react-breadcrumbs throwing error when using with router

React Breadcrumbs is throwing some error when using with Router.
I am following this tutorial for implementation.
http://learnreact.robbestad.com/breadcrumbs
Below is the code:
var Breadcrumbs = require('react-breadcrumbs');
const Routes = () => (
<BrowserRouter>
<div>
<Header />
<MegaMenu />
{Breadcrumbs}
<Route exact path='/' name='HomePage' component={HomePage}/>
<Route path='/celebrity' name='Celebrities' component={Celebrities}/>
<Route path='/axios' name='Axios' component={Axios}/>
<Route path='/brands' name='Brands' component={Brands}/>
<Footer />
</div>
</BrowserRouter>
);
export default Routes;
Below is the error:
Objects are not valid as a React child (found: object with keys {Breadcrumb, Breadcrumbs}). If you meant to render a collection of children, use an array instead.
You shouldn't pass the reference directly but use it with React.createElement or in other words, in JSX land you should do just <Breadcrumbs />.
If you look carefully at the code from the link you posted (http://learnreact.robbestad.com/breadcrumbs):
var Breadcrumbs = require('react-breadcrumbs');
MyComponent = React.createClass({
render: function() {
return (
<div>
<Breadcrumbs />{/* You see it here, <Breadcrumbs /> not {Breadcrumbs} */}
</div>
);
}
});
It creates new React element and now let's check your code:
var Breadcrumbs = require('react-breadcrumbs');
const Routes = () => (
<BrowserRouter>
<div>
<Header />
<MegaMenu />
{Breadcrumbs}{/* <-------- Here is the issue */}
<Route exact path='/' name='HomePage' component={HomePage}/>
<Route path='/celebrity' name='Celebrities' component={Celebrities}/>
<Route path='/axios' name='Axios' component={Axios}/>
<Route path='/brands' name='Brands' component={Brands}/>
<Footer />
</div>
</BrowserRouter>
);
export default Routes;
If you replace {Bredcrumbs} with <Breadcrumbs />, it should just work:
var Breadcrumbs = require('react-breadcrumbs');
const Routes = () => (
<BrowserRouter>
<div>
<Header />
<MegaMenu />
<Breadcrumbs />
<Route exact path='/' name='HomePage' component={HomePage}/>
<Route path='/celebrity' name='Celebrities' component={Celebrities}/>
<Route path='/axios' name='Axios' component={Axios}/>
<Route path='/brands' name='Brands' component={Brands}/>
<Footer />
</div>
</BrowserRouter>
);
export default Routes;
You can read more about JSX in the official React documentation:
https://reactjs.org/docs/introducing-jsx.html
I have used this library https://www.npmjs.com/package/react-breadcrumbs-dynamic][1] to implement the breadcrumbs.
Created one route.js and imported the library
import { Breadcrumb as BootstrapBreadcrumb } from 'react-bootstrap'
import { Breadcrumbs, BreadcrumbsItem } from 'react-breadcrumbs-dynamic';
import CrumbItem from '../components/common/breadcrumb/CrumbItem';
Created the breadcrumbs container like this in route.js:
const Routes = () => (
<BrowserRouter>
<div>
<div className="breadcrumbs-container">
<BreadcrumbsItem glyph='home' to={base_path}>
Home Page
</BreadcrumbsItem>
<Breadcrumbs
hideIfEmpty={{ active: true }}
item={CrumbItem}
container={BootstrapBreadcrumb}
finalProps={{ active: true }}
duplicateProps={{ to: 'href' }}
/>
</div>
<Route exact path='/' component={HomePage} />
<Route path='/brands' component={Brands} />
<Footer />
</div>
</BrowserRouter>
);
Given breadcrumbs items in Another component brands.js
import { BreadcrumbsItem } from 'react-breadcrumbs-dynamic';
render() {
return (
<BreadcrumbsItem to={'/brands'}>
Brands
</BreadcrumbsItem>
)
}
Created link container separately
import { Breadcrumb } from 'react-bootstrap'
import { LinkContainer } from 'react-router-bootstrap'
const CrumbItem = ({to, ...props}) => (
<LinkContainer to={to}>
<Breadcrumb.Item {...props}>
</Breadcrumb.Item>
</LinkContainer>
)
export default CrumbItem
Note: Using bootstrap is optional

How can I split React Router into multiple files

My routes file is getting rather messy so I decided to split them out into separate files.
My problem is that if I used 2 separate files, whichever comes after the first include does not get rendered:
const routes = (
<div>
<Switch>
<Route exact path="/" component={Home} />
{Registration} //Does get rendered
//Everything below this does not get a route
{Faq}
<Route path="/login" component={login} />
<Route component={NoMatch} />
</Switch>
</div>
);
If I switch Faq with registration then all the Faq routes will work.
RegistrationRoutes.js
import Introduction from '../containers/Registration/Introduction';
import Login from '../containers/Login';
const Routes = (
<Switch>
<Route path="/login" component={Login} key="login" />,
<Route path="/registration/introduction" component={Introduction} key="registration-intro" />
</Switch>
);
export default Routes;
FaqRoutes.js
import Faq from '../containers/Faq';
import faqJson from '../json_content/faq/faq';
import FaqCategory from '../containers/Faq/faqCategory';
const Routes = (
<Switch>
<Route path="/faq/:category" component={FaqCategory} key="faqCat" />
<Route path="/faq" render={props => <Faq data={faqJson} />} key="faq" />
</Switch>
);
export default Routes;
May be you can move them to config file and load them from there.
App.tsx
import routes from "./routes";
const App: React.FC = () => {
return (
<BrowserRouter>
<div>
<Switch>
{routes.data.map((entry) => {return (<Route {...entry}/>)})}
</Switch>
</div>
</BrowserRouter>
);
};
export default App;
router.ts
const routes = {data: [
{
key: "one",
path: "/three"
},
{
key: "two",
path: "/two"
}
]
}
export default routes;
This will keep your code simple
Your code would get translated to something like this,
const routes = (
<div>
<Switch>
<Route exact path="/" component={Home} />
<Switch>
<Route path="/login" component={Login} key="login" />,
<Route path="/registration/introduction"
component={Introduction} key="registration-intro" />
</Switch>
//Everything below this does not get a route
{Faq}
<Route path="/login" component={login} />
<Route component={NoMatch} />
</Switch>
</div>
);
This is wrong way to implement routing with react-router-dom or React-Router v4.
For Correct way of implementation You can see this example.
index.js
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Switch, Route, Link } from "react-router-dom";
import LandingPage from "../Registration";
const Home = () => {
return <div>
Home Component
<Link to="/auth/login">Login</Link>
</div>;
};
function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<BrowserRouter>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/auth" component={LandingPage} />
</Switch>
</BrowserRouter>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Registration.js
import React, { Component } from 'react';
import { Switch, Route, Link, Redirect } from 'react-router-dom';
const LoginRegister = (props) => {
return (
<div>
Login or register
<Link to="/login">Login</Link>
<br />
<Link to="/signup" >Signup</Link>
</div>
);
}
const Login = (props) =>{
console.log("login ", props);
return (
<div>
Login Component
<Link to="/auth/signup" >Signup</Link>
</div>
);
}
const Signup = () => (
<div>
Signup component
<Link to="/auth/login" >Login</Link>
</div>
);
class LandingPage extends Component {
render() {
console.log('Landing page',this.props);
const loginPath = this.props.match.path +'/login';
const signupPath = this.props.match.path + '/signup';
console.log(loginPath);
return (
<div className="container" >
Landing page
<Switch>
<Route path={loginPath} component={Login} />
<Route path={signupPath} component={Signup} />
<Route path="/" exact component={LoginRegister} />
</Switch>
</div>
);
}
}
export default LandingPage;
Try the following
RegistrationRoutes.js
import Introduction from '../containers/Registration/Introduction';
import Login from '../containers/Login';
const Routes = (
<React.Fragment>
<Route path="/login" component={Login} key="login" />,
<Route path="/registration/introduction" component={Introduction} key="registration-intro" />
</React.Fragment>
);
export default Routes;

React router dom and layouts

I want to use layouts with my react-router-dom, at this moment i am doing that like this
const DefaultLayout = ({children, ...rest}) => {
return (
<div className={styles.wrapper}>
<Header/>
{children}
<Footer/>
</div>
)
};
const DefaultRoute = ({component: Component, ...rest}) => {
return (
<Route {...rest} render={matchProps => (
<DefaultLayout>
<Component {...matchProps} />
</DefaultLayout>
)}/>
)
};
render(
<Provider store={store}>
<HashRouter>
<Switch>
<DefaultRoute exact path="/" component={AdvertList}/>
<DefaultRoute exact path="/user" component={UserOptions}/>
<Route path="/login" children={Login}/>
<Route render={
() => (
<div>
Not found
</div>
)
}/>
</Switch>
</HashRouter>
</Provider>,
document.querySelector('#app')
);
it works okay, both UserOptions and AdvertList components are rendered inside DefaultLayout, and Login component does not, but in official documentation i didn't find solution like that, instead there is "nested routing" where you adding new nested routes in subclasses, like
if you need default layout u make it on route /, then if you need advert list with that layout, in layout component you defined route /adverts and adding link to it, and so on, each sub component uses layout of parent one.
But in my case there is already product list on route /, and i need to change that content to other products list regarding link pressed, not to add to parent layout, but to change it part. Here is my code,
const { BrowserRouter, Route, Switch, Link } = window.ReactRouterDOM;
const { Component } = window.React;
const About = () => ('About');
const MiscProducts = () => ('Misc products');
class AdvertsList extends Component {
render() {
return (
<div className="container">
<header>Header</header>
<main>
<nav>
<Link to="/miscProducts">Misc Products</Link> #
<Link to="/about">About</Link>
</nav>
<div className="content">
Main Products
</div>
</main>
<footer>Footer</footer>
<Route path="/miscProducts" component={MiscProducts} />
</div>
)
};
};
class App extends Component {
render() {
return (
<BrowserRouter>
<Switch>
<Route path="/" component={AdvertsList} />
<Route path="/about" component={About} />
<Route path="*" render={
() => (
<div>
Not found
</div>
)
}/>
</Switch>
</BrowserRouter>
);
}
}
ReactDOM.render(<App />, document.querySelector("#app"));
http://jsfiddle.net/gmcke2a4/6/ here main products loaded by default, and when i press misc products, misc products must be loaded instead of main one.
p.s. And why about doesn't work?
Login Fix
<Route path="/login" children={Login}/> this seems wrong because children component expects function which return nodes i think.Try <Route path="/login" children={() => (</Login />)}
Layout
But in my case there is already product list on route /, and i need to
change that content to other products list regarding link pressed, not
to add to parent layout
You can create component which renders specific products like this.
const MainProducts = () => 'Main Products'
const GummyBearsProducts = () => 'GummyBears'
const Products = props => (
<div className="products-container">
<Switch>
<Route path={`${props.location.pathname}`} component={MainProducts}/>
<Route path={`${props.location.pathname}/gummy-bears`} components={GummyBearProducts}/>
</Switch>
</div>
)
And then use it as follows.
class AdvertsList extends Component {
render() {
return (
<div className="container">
<header>Header</header>
<main>
<nav>
<Link to="/products">Products</Link> #
<Link to="/about">About</Link>
</nav>
<div className="content">
<Route path="/products" component={Products} />
</div>
</main>
<footer>Footer</footer>
</div>
)
};
};
React router is great in rendering specific components.I hope it answers your question.Cheers!
If you are using react-router-dom v6. Then follow the below procedure to configure react-router-dom,
App.jsx:
import './App.css';
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import Home from './Components/Home'
import About from './Components/About'
import Layout from './Components/Layout'
function App() {
return (
<div className="App">
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
</Route>
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
After configuring the react router in App.jsx. I am creating 3 components Home, About and Layout. Home and About are regular components and Layout component is to handle the Layout part in react-router-dom using Outlet.
Layout.jsx
import { Outlet, Link } from 'react-router-dom'
export default function Layout() {
return (
<>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Outlet />
</>
)
}
Home.jsx
export default function Home() {
return (
<>
<p>This is Home</p>
</>
)
}
About.jsx
export default function About() {
return (
<>
<p>This is About Us</p>
</>
)
}

Categories

Resources