how to do dynamic routing in child component in reactjs? - javascript

In my case, i have 6 menu in my application. In header part i have 'Next' and 'back' buttons. If i click next button, it should navigate to next menu, for back button, it should navigate to previous page. and header.js is a seperate component. Code is attached below
app.js
render() {
return (
<Router>
<div className="h-100">
<Header />
<ContentNavigation />
<Switch>
<Route exact path='/' component={WelcomeMenu} />
<Route path='/principal' component={PrincipleMenu} />
<Route path='/mycar' component={MycarMenu} />
<Route path='/abc' component={abcMenu} />
<Route path='/ijkmenu' component={ijkMenu} />
<Route path='/xyzmenu' component={xyzMenu} />
</Switch>
</div>
</Router>
);
}
header.js
render() {
return (
<div className="header-right text-right header-text-pd-tp">
<span>
<i className ="icon-arrow-left prev-next-icon prev-icon"></i>
BACK
</span>
Current Chapter
<span>
NEXT
<i className="icon-arrow-right prev-next-icon next-icon" aria-hidden="true"></i>
</span>
</div>
)
}

This is one way to do routing
this.props.history.push({
pathname: '/your_route_path'
})

Multiple ways- you can navigate to other component.
1-using Link
import {Link} from 'react-router-dom'
<Link to="/ijkmenu">
NEXT
<i className="icon-arrow-right prev-next-icon next-icon" aria-hidden="true"></i>
</Link>
2-using this.props.history.push()
<span onClick={()=> this.props.history.push('/ijkmenu')}>
NEXT
<i className="icon-arrow-right prev-next-icon next-icon" aria-hidden="true"></i>
</span>

Related

onclick of sidebar item issue in react

i am trying to create a simple react project. it has a navbar, sidebar and the main content area.
first a home component is displayed.
home.js
import { useState } from "react";
import Navbar from "../navbar/navbar";
import Sidebar from "../sidebar/sidebar";
import "./style.css";
import { useSelector, useDispatch } from 'react-redux'
function Home() {
const sidebarOpen = useSelector((state) => state.sidebarOpenState);
return (
<>
<Navbar />
<div className="home-box d-flex">
{sidebarOpen && <div className="p-2 flex-fill"><Sidebar /></div>}
</div>
</>
);
}
export default Home;
my navbar has a button which will change state sidebarOpen.
my sidebar looks like this->
sidebar.js
import "./style.css";
import { Link } from "react-router-dom";
function Sidebar() {
return (
<div className="divSidebar">
<ul>
<li>
<Link to="/chess">
<img className="sidebar-img" src="images/sidebar/chess.png"></img>
<span className="sidebar-text">Chess</span>
</Link>
</li>
<li>
<Link to="/volleyball">
<img
className="sidebar-img"
src="images/sidebar/volleyball.png"
></img>
<span className="sidebar-text">Volleyball</span>
</Link>
</li>
<li>
<Link to="/football">
<img
className="sidebar-img"
src="images/sidebar/football.png"
></img>
<span className="sidebar-text">Football</span>
</Link>
</li>
<li>
<Link to="/tabletennis">
<img
className="sidebar-img"
src="images/sidebar/table-tennis.png"
></img>
<span className="sidebar-text">TableTennis</span>
</Link>
</li>
<li>
<Link to="/rugby">
<img className="sidebar-img" src="images/sidebar/rugby.png"></img>
<span className="sidebar-text">Rugby</span>
</Link>
</li>
</ul>
</div>
);
}
export default Sidebar;
when i click on chess, the respective component should be loaded.
chess.js
function Chess() {
return (
<>
<h1>chess</h1>
</>
);
}
export default Chess;
but the problem is my sidebar disappears. i only want the main content area to be changed nothing else. can someone help? let me know if u want to some more code.
---------edit
i have added console.log in two places. one is in the navbar where the toggle method is defined and another is in redux store where toggle state is defined. both the places onclick is working. i am able to see message but the sidebar is not getting rendered.
---------edit 2
App.js
import "./App.css";
import Navbar from "./components/navbar/navbar";
import { Route, Routes } from "react-router-dom";
import Chess from "./components/chess/chess";
import Volleyball from "./components/volleyball/volleyball";
import Football from "./components/football/football";
import TableTennis from "./components/tabletennis/tabletennis";
import Rugby from "./components/rugby/rugby";
import Home from "./components/home/home";
function App() {
return (
<div className="App">
<Routes>
<Route exact path="/" element={<Home />} />
<Route
path="/chess"
element={
<>
<Navbar />
<Chess />
</>
}
/>
<Route
path="/volleyball"
element={
<>
<Navbar />
<Volleyball />
</>
}
/>
<Route
path="/tabletennis"
element={
<>
<Navbar />
<TableTennis />
</>
}
/>
<Route
path="/football"
element={
<>
<Navbar />
<Football />
</>
}
/>
<Route
path="/rugby"
element={
<>
<Navbar />
<Rugby />
</>
}
/>
</Routes>
</div>
);
}
export default App;
When you click on Chess you navigate to "/chess"
So if u can't see your Navbar there, is because you have to render it there too.
Or, render the Navbar outside de Routes from BrowsterRouter.
We need to see the components rendering on "/chess" and the react-router-dom config on app.js (or on the top lvl you declare it)
----- edit ------
Ok, look this:
function App() {
return (
<BrowserRouter>
<NavBar />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/test" element={<Test />} />
</Routes>
</BrowserRouter>
);
}
If you refactor your brower like this is gona be more clean to understand the code and even easy to escale.
As u see, the navBar is outside the Routes, so its gona be visible in all routes.
then you can have this:
-> one path -> one element
your Links on navbar (or sidebar or whatelse) are gona work good.
i found a way. i rendered <Sidebar /> again in all my child components.
like this->
chess.js
function Chess() {
const sidebarOpen = useSelector((state) => state.sidebarOpenState);
return (
{sidebarOpen && (
<div className="p-2 flex-fill">
<Sidebar />
</div>
)}
)
}
this way when i click on button the state is updated and sidebar is rendered automatically.

how to create multi pages with different headers using react routes

I need to create 2 multi-pages UIs(managementUI and documentUI) with different headers.
updates:
the header contains navigation buttons to open and display different subpage components between the header and footer of the UI it belongs to.
e.g. the ApiCardGrid component will be displayed in managementUI.
However, the subpage cannot open in the outlet between header and footer when I clicked button in navigation header.
in App.tsx
function App() {
const [totalApiData, setTotalApiData] = useState([]);
useEffect(() => {
axios.get("/api-documents").then((res) => {
setTotalApiData(res.data);
});
}, []);
return (
<>
<div className="App">
<Router>
<Routes>
<Route
path="/apiManagement"
element={<ManagementUI />}
>
<Route
path="apis"
element={<ApiCardGrid spacing={2} size={3} />}
/>
</Route>
<Route
path="/documents"
element={<DocumentUI />}
></Route>
</Routes>
</Router>
</div>
</>
);
}
(update) Following comments made by #Drew Reese, in ManagementUI, I put an Outlet between header and footer to render the contents of subpages like ApiCardGrid. In ManagementUI.tsx:
function ManagementUI() {
const [totalApiData, setTotalApiData] = useState([]);
useEffect(() => {
axios.get("/api-documents").then((res) => {
setTotalApiData(res.data);
});
}, []);
return (
<>
<div className="management-ui">
<div className="management-header">
<Header />
</div>
<div className="management-content">
<Outlet />
</div>
<div className="management-footer">
<Footer />
</div>
</div>
</>
);
}
(update)API List button that link to /apis to display ApiCardGrid component in the Header:
<Header>
<Toolbar
disableGutters
variant="dense"
id="header-primary-navigation"
className="gds-primary-navigation"
>
<nav>
<Button className="gds-button-primary-navigation" href="/apiManagement/apis">
API List
</Button>
<Link to="/apiManagement/apis">API List</Link>
<Button className="gds-button-primary-navigation" href="/apiInfo">
API Info
</Button>
<Button className="gds-button-primary-navigation" href="/addApis">
Add API
</Button>
<Button
className="gds-button-primary-navigation active"
href="/active"
>
active page
</Button>
</nav>
</Toolbar>
</ Header>
similar in Header2
However, when I open UI1 localhost:3000/UI1, the UI1 opened successfully, but if I click button subpage1 to try to display subpage1 in UI1, the console responds error:"No routes matched location "/subpage1".(solved following answer of #Drew Reese)
update:
When I input url http://localhost:3000/apiManagement, the UI shows up. However, when I clicked the API List button, the url jumps to http://localhost:3000/apiManagement/apis, but the subpage item not shows up. I opened inspect tool, but no errors in console.
The subpage(ApiGridCard) supposed to display like
When rendering components on routes that render descendent routes the parent routes necessarily need to append the path wildcard "*" to their paths to allow descendent path matching.
Example:
<Router>
<Routes>
<Route
path="/UI1/*"
element={<UI1 />}
/>
<Route
path="/UI2/*"
element={<UI2 />}
/>
</Routes>
</Router>
An alternative is to create UI layout routes that render the appropriate header component and an Outlet for nested routes to render their element into.
Example:
import { Outlet } from 'react-router-dom';
const UI1 = () => (
<div >
<div >
<Header1 />
</div>
<div >
<Outlet />
</div>
<div >
<Footer />
</div>
</div>
);
const UI2 = () => (
<div >
<div >
<Header2 />
</div>
<div >
<Outlet />
</div>
<div >
<Footer />
</div>
</div>
);
...
<Router>
<Routes>
<Route path="/UI1" element={<UI1 />}>
<Route path="subpage1" element={<Subpage1 />} /> // "/UI1/subpage1"
<Route path="subpage2" element={<Subpage2 />} /> // "/UI1/subpage2"
</Route>
<Route path="/UI2" element={<UI2 />}>
<Route path="subpage3" element={<Subpage3 />} /> // "/UI2/subpage3"
<Route path="subpage4" element={<Subpage4 />} /> // "/UI2/subpage4"
</Route>
</Routes>
</Router>

How to change class when component is not equal to home than add class in header component in react.js?

I want to add a class in the header component when the route is not home. My code is:
App.js
<BrowserRouter>
<Header />
<Route exact path="/" component={Home}/>
<Route exact path="/shop" component={Shop}/>
<Route exact path="/contact" component={Contact}/>
<Footer />
</BrowserRouter>
Header.js component code:
<div className="all-category (here add-class when route is not equal to home)">
<h3 className="cat-heading"><i className="fa fa-bars" aria-hidden="true"></i>CATEGORIES</h3>
<ul className="main-category">
<li>New Arrivals <i className="fa fa-angle-right" aria-hidden="true"></i>
<ul className="sub-category">
<li>accessories</li>
<li>best selling</li>
<li>top 100 offer</li>
</ul>
</li>
</ul>
</div>
you can check props.history.location.pathname in the header component
Also make sure to wrap the header component in withRouter
eg:
const Header = props => {
return <div className={props.history.location.pathname === '/anything' ? "YOUR_CLASS":""}>....</div>
}
export default withRouter(Header)

React Routing: URL is changing but page is not loading

In React(v16.13.1), The URL is changing but page is not loading.
I found the similar questions ReactJS - React Router not changing component but url is changing
and React Router URL Change but Not Component in stack and i tried from different ways but none helps me.
It may be a small mistake, Please help to rectify this.
My code follows:
App.js file
import React, { Component } from "react";
import { BrowserRouter as Router, Route,Switch,Redirect } from "react-router-dom";
import TopNav from "./components/Navbar/TopNav";
import SideNav from "./components/Navbar/SideNav";
import Dashboard from "./components/Dashboard";
import Analytics from "./components/Analytics";
import ToDo from "./components/ToDo";
class App extends React.Component {
render() {
return (
<div>
<TopNav />
<SideNav />
<Router>
<Switch>
<Route exact path="/">
<Dashboard />
</Route>
<Route exact path="/analytics">
<Analytics />
</Route>
{/* <Route exact path="/analytics" component={Analytics}></Route> */}
<Route exact path="/todo">
<ToDo />
</Route>
<Redirect to="/"></Redirect>
</Switch>
</Router>
</div>
);
}
}
export default App;
SideNav.js page as follows:
import React from "react";
import { BrowserRouter as Router, Link } from "react-router-dom";
class SideNav extends React.Component {
render() {
return (
<div className="sidebar-wrapper">
<div className="sidebar-container">
<Router>
<ul className="sidebar-menu">
<li className="active">
<i className="fa fa-cubes"></i>
<Link className="link" to="/">
Dashboard
</Link>
</li>
<li>
<i className="fa fa-pie-chart"></i>
<Link className="link" to="/analytics">
Analytics
</Link>
</li>
<li>
<i className="fa fa-medkit"></i>
<Link className="link" to="/todo">
What to do?
</Link>
</li>
</ul>
</Router>
</div>
</div>
);
}
}
export default SideNav;
Thanks in advance!
You only need one <Router> at top level of your app.
You are already using <Router> in your App component.
Wrap the SideNav component in the Router and remove the Router used in SideNav.
import React, { Component } from "react";
import {
BrowserRouter as Router,
Route,
Switch,
Redirect,
Link
} from "react-router-dom";
class SideNav extends Component {
render() {
return (
<div className="sidebar-wrapper">
<div className="sidebar-container">
{/* <Router> */}
<ul className="sidebar-menu">
<li className="active">
<i className="fa fa-cubes" />
<Link className="link" to="/">
Dashboard
</Link>
</li>
<li>
<i className="fa fa-pie-chart" />
<Link className="link" to="/analytics">
Analytics
</Link>
</li>
<li>
<i className="fa fa-medkit" />
<Link className="link" to="/todo">
What to do?
</Link>
</li>
</ul>
{/* </Router> */}
</div>
</div>
);
}
}
class App extends Component {
render() {
return (
<div>
<Router>
<SideNav />
<Switch>
<Route exact path="/">
<div>/</div>
</Route>
<Route exact path="/analytics">
<div>ana</div>
</Route>
<Route exact path="/todo">
<div>todo</div>
</Route>
<Redirect to="/" />
</Switch>
</Router>
</div>
);
}
}
export default App;
Your <SideNav /> and the main content are in seperate <Router />s. They don't see each other, and they can't work together.
Think, like two iframes navigaing independantly of each other, just without the actual iframes.
Everything that reqiures the router, basically your entire app, needs to be inside a single <Router />.
import React, { Component } from "react";
import { BrowserRouter as Router, Route, Switch, Redirect } from "react-router-dom";
import TopNav from "./components/Navbar/TopNav";
import SideNav from "./components/Navbar/SideNav";
import Dashboard from "./components/Dashboard";
import Analytics from "./components/Analytics";
import ToDo from "./components/ToDo";
class App extends React.Component {
render() {
return (
<Router>
<TopNav />
<SideNav />
<Switch>
<Route exact path="/">
<Dashboard />
</Route>
<Route exact path="/analytics">
<Analytics />
</Route>
{/* <Route exact path="/analytics" component={Analytics}></Route> */}
<Route exact path="/todo">
<ToDo />
</Route>
<Redirect to="/"></Redirect>
</Switch>
</Router>
);
}
}
export default App;
SideNav.js
import React from "react";
import { BrowserRouter as Router, Link } from "react-router-dom";
class SideNav extends React.Component {
render() {
return (
<div className="sidebar-wrapper">
<div className="sidebar-container">
<ul className="sidebar-menu">
<li className="active">
<i className="fa fa-cubes"></i>
<Link className="link" to="/">
Dashboard
</Link>
</li>
<li>
<i className="fa fa-pie-chart"></i>
<Link className="link" to="/analytics">
Analytics
</Link>
</li>
<li>
<i className="fa fa-medkit"></i>
<Link className="link" to="/todo">
What to do?
</Link>
</li>
</ul>
</div>
</div>
);
}
}
The same applies for the TopNav.js.

Wrapping <button>'s in <Link to=''> using react-router

I have 3 buttons that link to different pages. The main page is the only page that is supposed to display the buttons (App.js). I've created two more pages, table1.js, table2.js, table3.js that all display different things. My problem is, when I click either one of the buttons, it directs me to the right page (e.g. http://localhost:3000/table1) but the buttons are still being displayed. Is there a way I can do something like "remove buttons after user is directed to new page"?
class App extends Component {
render() {
return (
<div className="App">
<form className='button-container'>
<Router>
<div>
<Route exact path='/table1' component={table1}/>
<Link to="/table1" className='button'>
<button className='button' type="button">
Table 1
</button>
</Link>
</div>
<div>
<Route exact path='/table2' component={table2}/>
<Link to="/table2" className='button'>
<button className='button' type="button">
Table 2
</button>
</Link>
</div>
<div>
<Route exact path='/table3' component={table3}/>
<Link to="/table3" className='button'>
<button className='button' type="button">
Table 3
</button>
</Link>
</div>
</Router>
</form>
</div>
);
}
}
export default App;
You should probably separate you're routing buttons into a different component and only render the buttons based on a route or condition as well:
class Navigation extends Component {
render() {
return (
<form className="button-container">
<Link to="/table1" className="button">
<button className="button" type="button">
Table 1
</button>
</Link>
<Link to="/table2" className="button">
<button className="button" type="button">
Table 2
</button>
</Link>
<Link to="/table3" className="button">
<button className="button" type="button">
Table 3
</button>
</Link>
</form>
);
}
}
class App extends Component {
render() {
return (
<div className="App">
<Router>
<Switch> {/* only matches one route */}
<Route exact path="/table1" component={table1} />
<Route exact path="/table2" component={table2} />
<Route exact path="/table3" component={table3} />
<Route component={Navigation} /> {/* If no routes matched show Navigation */}
</Switch>
</Router>
</div>
);
}
}
export default App;

Categories

Resources