React router dom and layouts - javascript

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>
</>
)
}

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>
);
}

Nested route doesn't render component

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.)

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

Nested routes with react router v4 / v5

I am currently struggling with nesting routes using react router v4.
The closest example was the route config in the
React-Router v4 Documentation.
I want to split my app in 2 different parts.
A frontend and an admin area.
I was thinking about something like this:
<Match pattern="/" component={Frontpage}>
<Match pattern="/home" component={HomePage} />
<Match pattern="/about" component={AboutPage} />
</Match>
<Match pattern="/admin" component={Backend}>
<Match pattern="/home" component={Dashboard} />
<Match pattern="/users" component={UserPage} />
</Match>
<Miss component={NotFoundPage} />
The frontend has a different layout and style than the admin area. So within the frontpage the route home, about and so one should be the child routes.
/home should be rendered into the Frontpage component and /admin/home should be rendered within the Backend component.
I tried some other variations but I always ended in not hitting /home or /admin/home.
Final solution:
This is the final solution I am using right now. This example also has a global error component like a traditional 404 page.
import React, { Component } from 'react';
import { Switch, Route, Redirect, Link } from 'react-router-dom';
const Home = () => <div><h1>Home</h1></div>;
const User = () => <div><h1>User</h1></div>;
const Error = () => <div><h1>Error</h1></div>
const Frontend = props => {
console.log('Frontend');
return (
<div>
<h2>Frontend</h2>
<p><Link to="/">Root</Link></p>
<p><Link to="/user">User</Link></p>
<p><Link to="/admin">Backend</Link></p>
<p><Link to="/the-route-is-swiggity-swoute">Swiggity swooty</Link></p>
<Switch>
<Route exact path='/' component={Home}/>
<Route path='/user' component={User}/>
<Redirect to={{
state: { error: true }
}} />
</Switch>
<footer>Bottom</footer>
</div>
);
}
const Backend = props => {
console.log('Backend');
return (
<div>
<h2>Backend</h2>
<p><Link to="/admin">Root</Link></p>
<p><Link to="/admin/user">User</Link></p>
<p><Link to="/">Frontend</Link></p>
<p><Link to="/admin/the-route-is-swiggity-swoute">Swiggity swooty</Link></p>
<Switch>
<Route exact path='/admin' component={Home}/>
<Route path='/admin/user' component={User}/>
<Redirect to={{
state: { error: true }
}} />
</Switch>
<footer>Bottom</footer>
</div>
);
}
class GlobalErrorSwitch extends Component {
previousLocation = this.props.location
componentWillUpdate(nextProps) {
const { location } = this.props;
if (nextProps.history.action !== 'POP'
&& (!location.state || !location.state.error)) {
this.previousLocation = this.props.location
};
}
render() {
const { location } = this.props;
const isError = !!(
location.state &&
location.state.error &&
this.previousLocation !== location // not initial render
)
return (
<div>
{
isError
? <Route component={Error} />
: <Switch location={isError ? this.previousLocation : location}>
<Route path="/admin" component={Backend} />
<Route path="/" component={Frontend} />
</Switch>}
</div>
)
}
}
class App extends Component {
render() {
return <Route component={GlobalErrorSwitch} />
}
}
export default App;
In react-router-v4 you don't nest <Routes />. Instead, you put them inside another <Component />.
For instance
<Route path='/topics' component={Topics}>
<Route path='/topics/:topicId' component={Topic} />
</Route>
should become
<Route path='/topics' component={Topics} />
with
const Topics = ({ match }) => (
<div>
<h2>Topics</h2>
<Link to={`${match.url}/exampleTopicId`}>
Example topic
</Link>
<Route path={`${match.path}/:topicId`} component={Topic}/>
</div>
)
Here is a basic example straight from the react-router documentation.
react-router v6
Update for 2022 - v6 has nested Route components that Just Work™.
This question is about v4/v5, but the best answer now is just use v6 if you can!
See example code in this blog post. If you can't upgrade just yet, however...
react-router v4 & v5
It's true that in order to nest Routes you need to place them in the child component of the Route.
However if you prefer a more inline syntax rather than breaking your Routes up across components, you can provide a functional component to the render prop of the Route you want to nest under.
<BrowserRouter>
<Route path="/" component={Frontpage} exact />
<Route path="/home" component={HomePage} />
<Route path="/about" component={AboutPage} />
<Route
path="/admin"
render={({ match: { url } }) => (
<>
<Route path={`${url}/`} component={Backend} exact />
<Route path={`${url}/home`} component={Dashboard} />
<Route path={`${url}/users`} component={UserPage} />
</>
)}
/>
</BrowserRouter>
If you're interested in why the render prop should be used, and not the component prop, it's because it stops the inline functional component from being remounted on every render. See the documentation for more detail.
Note the example wraps the nested Routes in a Fragment. Prior to React 16, you can use a container <div> instead.
Just wanted to mention react-router v4 changed radically since this question was posted/answed.
There is no <Match> component any more! <Switch>is to make sure only the first match is rendered. <Redirect> well .. redirects to another route. Use or leave out exact to either in- or exclude a partial match.
See the docs. They are great. https://reacttraining.com/react-router/
Here's an example I hope is useable to answer your question.
<Router>
<div>
<Redirect exact from='/' to='/front'/>
<Route path="/" render={() => {
return (
<div>
<h2>Home menu</h2>
<Link to="/front">front</Link>
<Link to="/back">back</Link>
</div>
);
}} />
<Route path="/front" render={() => {
return (
<div>
<h2>front menu</h2>
<Link to="/front/help">help</Link>
<Link to="/front/about">about</Link>
</div>
);
}} />
<Route exact path="/front/help" render={() => {
return <h2>front help</h2>;
}} />
<Route exact path="/front/about" render={() => {
return <h2>front about</h2>;
}} />
<Route path="/back" render={() => {
return (
<div>
<h2>back menu</h2>
<Link to="/back/help">help</Link>
<Link to="/back/about">about</Link>
</div>
);
}} />
<Route exact path="/back/help" render={() => {
return <h2>back help</h2>;
}} />
<Route exact path="/back/about" render={() => {
return <h2>back about</h2>;
}} />
</div>
</Router>
Hope it helped, let me know. If this example is not answering your question well enough, tell me and I'll see if I can modify it.
I succeeded in defining nested routes by wrapping with Switch and define nested route before than root route.
<BrowserRouter>
<Switch>
<Route path="/staffs/:id/edit" component={StaffEdit} />
<Route path="/staffs/:id" component={StaffShow} />
<Route path="/staffs" component={StaffIndex} />
</Switch>
</BrowserRouter>
Reference: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/Switch.md
Using Hooks
The latest update with hooks is to use useRouteMatch.
Main routing component
export default function NestingExample() {
return (
<Router>
<Switch>
<Route path="/topics">
<Topics />
</Route>
</Switch>
</Router>
);
}
Child component
function Topics() {
// The `path` lets us build <Route> paths
// while the `url` lets us build relative links.
let { path, url } = useRouteMatch();
return (
<div>
<h2>Topics</h2>
<h5>
<Link to={`${url}/otherpath`}>/topics/otherpath/</Link>
</h5>
<ul>
<li>
<Link to={`${url}/topic1`}>/topics/topic1/</Link>
</li>
<li>
<Link to={`${url}/topic2`}>/topics/topic2</Link>
</li>
</ul>
// You can then use nested routing inside the child itself
<Switch>
<Route exact path={path}>
<h3>Please select a topic.</h3>
</Route>
<Route path={`${path}/:topicId`}>
<Topic />
</Route>
<Route path={`${path}/otherpath`>
<OtherPath/>
</Route>
</Switch>
</div>
);
}
Some thing like this.
import React from 'react';
import {
BrowserRouter as Router, Route, NavLink, Switch, Link
} from 'react-router-dom';
import '../assets/styles/App.css';
const Home = () =>
<NormalNavLinks>
<h1>HOME</h1>
</NormalNavLinks>;
const About = () =>
<NormalNavLinks>
<h1>About</h1>
</NormalNavLinks>;
const Help = () =>
<NormalNavLinks>
<h1>Help</h1>
</NormalNavLinks>;
const AdminHome = () =>
<AdminNavLinks>
<h1>root</h1>
</AdminNavLinks>;
const AdminAbout = () =>
<AdminNavLinks>
<h1>Admin about</h1>
</AdminNavLinks>;
const AdminHelp = () =>
<AdminNavLinks>
<h1>Admin Help</h1>
</AdminNavLinks>;
const AdminNavLinks = (props) => (
<div>
<h2>Admin Menu</h2>
<NavLink exact to="/admin">Admin Home</NavLink>
<NavLink to="/admin/help">Admin Help</NavLink>
<NavLink to="/admin/about">Admin About</NavLink>
<Link to="/">Home</Link>
{props.children}
</div>
);
const NormalNavLinks = (props) => (
<div>
<h2>Normal Menu</h2>
<NavLink exact to="/">Home</NavLink>
<NavLink to="/help">Help</NavLink>
<NavLink to="/about">About</NavLink>
<Link to="/admin">Admin</Link>
{props.children}
</div>
);
const App = () => (
<Router>
<div>
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/help" component={Help}/>
<Route path="/about" component={About}/>
<Route exact path="/admin" component={AdminHome}/>
<Route path="/admin/help" component={AdminHelp}/>
<Route path="/admin/about" component={AdminAbout}/>
</Switch>
</div>
</Router>
);
export default App;
A complete answer for React Router v6 or version 6 just in case needed.
import Dashboard from "./dashboard/Dashboard";
import DashboardDefaultContent from "./dashboard/dashboard-default-content";
import { Route, Routes } from "react-router";
import { useRoutes } from "react-router-dom";
/*Routes is used to be Switch*/
const Router = () => {
return (
<Routes>
<Route path="/" element={<LandingPage />} />
<Route path="games" element={<Games />} />
<Route path="game-details/:id" element={<GameDetails />} />
<Route path="dashboard" element={<Dashboard />}>
<Route path="/" element={<DashboardDefaultContent />} />
<Route path="inbox" element={<Inbox />} />
<Route path="settings-and-privacy" element={<SettingsAndPrivacy />} />
<Route path="*" element={<NotFound />} />
</Route>
<Route path="*" element={<NotFound />} />
</Routes>
);
};
export default Router;
import DashboardSidebarNavigation from "./dashboard-sidebar-navigation";
import { Grid } from "#material-ui/core";
import { Outlet } from "react-router";
const Dashboard = () => {
return (
<Grid
container
direction="row"
justify="flex-start"
alignItems="flex-start"
>
<DashboardSidebarNavigation />
<Outlet />
</Grid>
);
};
export default Dashboard;
Github repo is here. https://github.com/webmasterdevlin/react-router-6-demo
React Router v6
allows to use both nested routes (like in v3) and separate, splitted routes (v4, v5).
Nested Routes
Keep all routes in one place for small/medium size apps:
<Routes>
<Route path="/" element={<Home />} >
<Route path="user" element={<User />} />
<Route path="dash" element={<Dashboard />} />
</Route>
</Routes>
const App = () => {
return (
<BrowserRouter>
<Routes>
// /js is start path of stack snippet
<Route path="/js" element={<Home />} >
<Route path="user" element={<User />} />
<Route path="dash" element={<Dashboard />} />
</Route>
</Routes>
</BrowserRouter>
);
}
const Home = () => {
const location = useLocation()
return (
<div>
<p>URL path: {location.pathname}</p>
<Outlet />
<p>
<Link to="user" style={{paddingRight: "10px"}}>user</Link>
<Link to="dash">dashboard</Link>
</p>
</div>
)
}
const User = () => <div>User profile</div>
const Dashboard = () => <div>Dashboard</div>
ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://unpkg.com/react#16.13.1/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom#16.13.1/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/history#5.0.0/umd/history.production.min.js"></script>
<script src="https://unpkg.com/react-router#6.0.0-alpha.5/umd/react-router.production.min.js"></script>
<script src="https://unpkg.com/react-router-dom#6.0.0-alpha.5/umd/react-router-dom.production.min.js"></script>
<script>var { BrowserRouter, Routes, Route, Link, Outlet, useNavigate, useLocation } = window.ReactRouterDOM;</script>
Alternative: Define your routes as plain JavaScript objects via useRoutes.
Separate Routes
You can use separates routes to meet requirements of larger apps like code splitting:
// inside App.jsx:
<Routes>
<Route path="/*" element={<Home />} />
</Routes>
// inside Home.jsx:
<Routes>
<Route path="user" element={<User />} />
<Route path="dash" element={<Dashboard />} />
</Routes>
const App = () => {
return (
<BrowserRouter>
<Routes>
// /js is start path of stack snippet
<Route path="/js/*" element={<Home />} />
</Routes>
</BrowserRouter>
);
}
const Home = () => {
const location = useLocation()
return (
<div>
<p>URL path: {location.pathname}</p>
<Routes>
<Route path="user" element={<User />} />
<Route path="dash" element={<Dashboard />} />
</Routes>
<p>
<Link to="user" style={{paddingRight: "5px"}}>user</Link>
<Link to="dash">dashboard</Link>
</p>
</div>
)
}
const User = () => <div>User profile</div>
const Dashboard = () => <div>Dashboard</div>
ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://unpkg.com/react#16.13.1/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom#16.13.1/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/history#5.0.0/umd/history.production.min.js"></script>
<script src="https://unpkg.com/react-router#6.0.0-alpha.5/umd/react-router.production.min.js"></script>
<script src="https://unpkg.com/react-router-dom#6.0.0-alpha.5/umd/react-router-dom.production.min.js"></script>
<script>var { BrowserRouter, Routes, Route, Link, Outlet, useNavigate, useLocation } = window.ReactRouterDOM;</script>
You can try something like
Routes.js
import React, { Component } from 'react'
import { BrowserRouter as Router, Route } from 'react-router-dom';
import FrontPage from './FrontPage';
import Dashboard from './Dashboard';
import AboutPage from './AboutPage';
import Backend from './Backend';
import Homepage from './Homepage';
import UserPage from './UserPage';
class Routes extends Component {
render() {
return (
<div>
<Route exact path="/" component={FrontPage} />
<Route exact path="/home" component={Homepage} />
<Route exact path="/about" component={AboutPage} />
<Route exact path="/admin" component={Backend} />
<Route exact path="/admin/home" component={Dashboard} />
<Route exact path="/users" component={UserPage} />
</div>
)
}
}
export default Routes
App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import { BrowserRouter as Router, Route } from 'react-router-dom'
import Routes from './Routes';
class App extends Component {
render() {
return (
<div className="App">
<Router>
<Routes/>
</Router>
</div>
);
}
}
export default App;
I think you can achieve the same from here also.
A complete answer for React Router v5.
const Router = () => {
return (
<Switch>
<Route path={"/"} component={LandingPage} exact />
<Route path={"/games"} component={Games} />
<Route path={"/game-details/:id"} component={GameDetails} />
<Route
path={"/dashboard"}
render={({ match: { path } }) => (
<Dashboard>
<Switch>
<Route
exact
path={path + "/"}
component={DashboardDefaultContent}
/>
<Route path={`${path}/inbox`} component={Inbox} />
<Route
path={`${path}/settings-and-privacy`}
component={SettingsAndPrivacy}
/>
<Redirect exact from={path + "/*"} to={path} />
</Switch>
</Dashboard>
)}
/>
<Route path="/not-found" component={NotFound} />
<Redirect exact from={"*"} to={"/not-found"} />
</Switch>
);
};
export default Router;
const Dashboard = ({ children }) => {
return (
<Grid
container
direction="row"
justify="flex-start"
alignItems="flex-start"
>
<DashboardSidebarNavigation />
{children}
</Grid>
);
};
export default Dashboard;
Github repo is here. https://github.com/webmasterdevlin/react-router-5-demo
I prefer to use react function. This solution is short and more readable
const MainAppRoutes = () => (
<Switch>
<Route exact path='/' component={HomePage} />
{AdminRoute()}
{SampleRoute("/sample_admin")}
</Switch>
);
/*first implementation: without params*/
const AdminRoute = () => ([
<Route path='/admin/home' component={AdminHome} />,
<Route path='/admin/about' component={AdminAbout} />
]);
/*second implementation: with params*/
const SampleRoute = (main) => ([
<Route path={`${main}`} component={MainPage} />,
<Route path={`${main}/:id`} component={MainPage} />
]);
**This code worked for me with v6**
index.js
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<Routes>
<Route path="/" element={<App />}>
<Route path="login" element={<Login />} />
<Route path="home" element={<Home />} />
</Route>
</Routes>
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root')
);
App.js:
function App(props) {
useEffect(() => {
console.log('reloaded');
// Checking, if Parent component re-rendering or not *it should not be, in the sense of performance*, this code doesn't re-render parent component while loading children
});
return (
<div className="App">
<Link to="login">Login</Link>
<Link to="home">Home</Link>
<Outlet /> // This line is important, otherwise we will be shown with empty component
</div>
);
}
login.js:
const Login = () => {
return (
<div>
Login Component
</div>
)
};
home.js:
const Home= () => {
return (
<div>
Home Component
</div>
)
};
interface IDefaultLayoutProps {
children: React.ReactNode
}
const DefaultLayout: React.SFC<IDefaultLayoutProps> = ({children}) => {
return (
<div className="DefaultLayout">
{children}
</div>
);
}
const LayoutRoute: React.SFC<IDefaultLayoutRouteProps & RouteProps> = ({component: Component, layout: Layout, ...rest}) => {
const handleRender = (matchProps: RouteComponentProps<{}, StaticContext>) => (
<Layout>
<Component {...matchProps} />
</Layout>
);
return (
<Route {...rest} render={handleRender}/>
);
}
const ScreenRouter = () => (
<BrowserRouter>
<div>
<Link to="/">Home</Link>
<Link to="/counter">Counter</Link>
<Switch>
<LayoutRoute path="/" exact={true} layout={DefaultLayout} component={HomeScreen} />
<LayoutRoute path="/counter" layout={DashboardLayout} component={CounterScreen} />
</Switch>
</div>
</BrowserRouter>
);

Categories

Resources