React - How to navigate to next popup view using route? - javascript

I have tried to find a solution to this problem without success. So I have a popup view and the idea is to navigate to a new view(component) within the popup using route. This is what I have so far:
This is the Popup component that opens when triggered:
import styled from "styled-components";
import { BrowserRouter as Router, Link as LinkR, Switch, Route } from "react-router-dom";
export const NavBtn = styled(LinkR)`
`;
export default function App(props) {
return (
<div className="ms-welcome">
<LogoWrap>
<LogoBtn>
<LogoText>Welcome to the first popup view</LogoText>
</LogoBtn>
</LogoWrap>
<hr />
<Router>
<Switch>
<NavBtn to="/PopupSecondView">
<NavBtnLink>Next window</NavBtnLink>
</NavBtn>
<Route path="/PopupSecondView" component={SecondView} />
</Switch>
</Router>
</div>
);
}
This is my second popup view(component):
export default function SecondView(props) {
return (
<div >
<LogoWrap>
<LogoBtn>
<LogoText>Welcome to the second view</LogoText>
</LogoBtn>
</LogoWrap>
<hr />
<NavBtn>
<NavBtnLink >Previous window</NavBtnLink>
</NavBtn>
</div>
);
}
This is my App.js which is not located at the root of my project. It is located inside the same folder as the popup component:
export default function App(props) {
return (
<div className="ms-welcome">
<Router>
<Switch>
<Route path="/PopupSecondView" component={SecondView} />
</Switch>
</Router>
<LogoWrap>
<LogoBtn>
<AiFillHome />
<LogoText>Virta</LogoText>
</LogoBtn>
<LogoBtn>
<AiOutlineInfoCircle />
<LogoText>Info</LogoText>
</LogoBtn>
<LogoBtn>
<VscRefresh />
<LogoText>Update</LogoText>
</LogoBtn>
</LogoWrap>
<Button
className="ms-welcome__action"
buttonType={ButtonType.hero}
iconProps={{ iconName: "ChevronRight" }}
onClick={click}
>
Open popup dialog window demo
</Button>
<hr />
</div>
);
}
Help would be highly appreciated!

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.

Component is not getting renderend properly with react-router

function App() {
return (
//BEM naming convention
<div className="app">
<div className="app__body">
<Sidebar />
<Chat />
<Router>
<Routes>
<Route exact path="/arroz" element={<MainPage />} />
</Routes>
</Router>
</div>
</div>
);
}
export default App;
can someone explain me why when i inicialize app, its rendering as supposed to and when i try to render the same thing but with the components inside this one component, it looses the css i have done and only uses a small part of screen. also when i render the page, it should only render the component, but instead is also rendering code that shouldnt be read.
how its being rendered
how it should be rendering
import React from "react";
import Chat from "./Chat";
import Sidebar from "./Sidebar";
function MainPage() {
return (
<div className="mainPage">
<Sidebar />
<Chat />
</div>
);
}
export default MainPage;
obs: i didnt styled MainPage.css and as i was inspecting the page the compenent had "display:block" dont know the meaning
i have done this and this works as i want, still i would like to understand why is not taking the form its suposed to
function App() {
return (
//BEM naming convention
<div className="app">
<div className="app__body">
<Sidebar />
<Router>
<Routes>
<Route exact path="/rooms/:roomId" element={<Chat />} />
</Routes>
</Router>
</div>
</div>
);
}
export default App;
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<BrowserRouter>
<App />
</BrowserRouter>
);
it seems if i put this on indeex and change the app like this it works has it suposed to
function App() {
return (
//BEM naming convention
<div className="app">
<div className="app__body">
<Sidebar />
<Routes>
<Route exact path="/rooms/:roomId" element={<Chat />} />
</Routes>
</div>
</div>
);
}
export default App;

How do I make Portal be a single page all on it own

Sorry, extreme React newbie. I have a simple react function component:
import React from "react";
export default function Portal() {
return (
<h2>Portal</h2>
);
}
In my App.js I have:
import React from 'react';
import { BrowserRouter, Route, Switch } from "react-router-dom";
import './App.css';
import Portal from "./components/Portal/portal";
import LogoHeader from './components/LogoHeader';
import NewFooter from "./components/NewFooter";
function App() {
return (
<div className="App">
<BrowserRouter>
<Switch>
<Route path="/portal">
<Portal />
</Route>
</Switch>
</BrowserRouter>
...
<LogoHeader />
...
<NewFooter/>
</div>
);
}
export default App;
In LogoHeader I have a link:
<a href='/Portal'>Portal</a>
When I click the "Portal" link it refreshes the page, but it now displays the "Portal" header at the top and then the rest of the App.js page. How do I make Portal be a single page all on it own?
UPDATE
Based on an Answer given by #DrewReese I have changed App.js Render to:
return (
<div className="App">
<BrowserRouter>
<p className="greeting">Hello, {token.firstName}</p>
<LogoHeader />
<GetCategories />
<Navbar id="customNav" navItems={navItems} shopCategories={shopCategories} />
<Switch>
<Route path="/home">
<Slideshow id="slideshow" />
<div id="productContainer">
<br />
<h3>Featured Products</h3>
<br />
<FeaturedCards />
<br />
<h3>Most Popular</h3>
<br />
<ProdCard />
<br />
<h3>New Products</h3>
<br />
<ProdCard />
</div>
</Route>
<Route path="/portal">
<Portal />
</Route>
</Switch>
<NewFooter />
</BrowserRouter>
</div>
);
When you use an anchor tag (<a href="...." />) it will trigger a page reload, which reloads your React app. You should use the Link component to link to pages within your app.
LogoHeader
import { Link } from 'react-router-dom';
...
<Link to='/portal'>Portal</Link>
If you want the header to display rendered pages then move it up in the JSX. Remember, any links you render need to be rendered within a routing context, so the header should be rendered within the BrowserRouter component.
App
function App() {
return (
<div className="App">
<BrowserRouter>
<LogoHeader />
<Switch>
<Route path="/portal">
<Portal />
</Route>
</Switch>
<NewFooter/>
</BrowserRouter>
</div>
);
}
If you want the Portal page to be rendered and the header not to be rendered, then you can render a custom header and conditionally render LogoHeader based on route matching.
useRouteMatch
matchPath props
It returns null when provided pathname does not match path prop.
const Header = () => {
const match = useRouteMatch("/portal");
return !match ? <LogoHeader /> : null;
}
function App() {
return (
<div className="App">
<BrowserRouter>
<Header />
<Switch>
<Route path="/portal">
<Portal />
</Route>
</Switch>
<NewFooter/>
</BrowserRouter>
</div>
);
}
Update
Within the Switch component, path order and specificity matter. Order more specific paths before less specific paths. "/portal" is more specific than "/" so it should be rendered earlier. This is because the Switch component exclusively matches and renders routes (i.e. only the first match found), as opposed to the Router that inclusively renders them (i.e. all matches).
return (
<div className="App">
<BrowserRouter>
<p className="greeting">Hello, {token.firstName}</p>
<LogoHeader />
<GetCategories />
<Navbar id="customNav" navItems={navItems} shopCategories={shopCategories} />
<Switch>
<Route path="/portal">
<Portal />
</Route>
<Route path="/">
<Slideshow id="slideshow" />
<div id="productContainer">
<br />
<h3>Featured Products</h3>
<br />
<FeaturedCards />
<br />
<h3>Most Popular</h3>
<br />
<ProdCard />
<br />
<h3>New Products</h3>
<br />
<ProdCard />
</div>
</Route>
</Switch>
<NewFooter />
</BrowserRouter>
</div>
);
I suppose you just need to use <Link to="/portal"> from react-router here.
import { Link } from 'react-router-dom' (v4 of react-router)
import { Link } from 'react-router' (v3 of react-router)
There are 2 issues with using a tag:
it does contains relative urls (for this particular case it won't be a problem, but it confuse you on some pages).
it triggers page refresh
More info about using Link
https://reactrouter.com/web/guides/quick-start

ReactJS react-router-dom - Components not showing

I am new here but a long time reader of StackOverflow content!
I am new to React and have a simple question about Multi-Pages App.
I did start to work on a website for a friend, I started with a one-pager but finally I did realize that I will need more then only one page. I installed react-router-dom and tried to set it up, the website doesn't return any errors, but only the SideBarMenu component is showing up !
the content of Home is not showing on / , same for the rest on /audio, /video, /images... And the weirdest part of it, if I write as URL for example some random thing like /asiomaos9j, it still show a blank website with the SideBarMenu without even crashing...
Anyone know why all my component on Home are not showing? Or even on /images the js file only contains a div with a H1 inside and this H1 not showing either... I can't figure out what I am doing wrong with this !
I did import as follow:
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
Then here is my App.js :
export default function App() {
return (
<React.StrictMode>
<Routes />
</React.StrictMode>
);
}
My Routes.js :
export default function Routes() {
return (
<Router>
<Switch>
<Route exact path='/' component={Home}></Route>
<Route exact path="/audio" component={AudioPlayerApp}></Route>
<Route exact path="/video" component={VideoPlayerApp}></Route>
<Route exact path="/images" component={ImagesApp}></Route>
</Switch>
<SideBarMenu pageWrapId={"page-wrap"} outerContainerId={"app"} />
</Router>
);
}
Finally as example, here is my Home.js
function Home(){
return(
<React.Fragment>
<Header />
<Services />
<ServicesContent />
<Media />
<MediaContent />
<Studio />
<StudioContent />
<Partenaires />
<PartenairesContent />
<Contact />
<ContactContent />
<Footer />
</React.Fragment>
)
}
export default Home;
Here as asked, SideBarMenu.js :
import React from 'react';
import { slide as Menu } from 'react-burger-menu';
import './components_css/SideBarMenu.css';
export default props =>{
return(
<Menu {...props}>
<a className="menu-item" href="#">
<span>+</span>Accueil
</a>
<a className="menu-item" href="#services_link">
<span>+</span>Services
</a>
<a className="menu-item" href="#media_link">
<span>+</span>Médias
</a>
<a className="menu-item" href="#studio_link">
<span>+</span>Studio
</a>
<a className="menu-item" href="#contact_link">
<span>+</span>Contact
</a>
</Menu>
);
};
These are links inside the Home page for the moment.
Take the exact out of the home route and place it at the end of all others

React Router is leaving my main page loaded when trying to load other pages

I have a MainPage that is loaded in App.js but when I use Browser Router and Route it will keep the MainPage and loads the second page over the top of it. Any tips would be helpful.
class App extends Component {
render() {
return(
<BrowserRouter>
<div className="App">
<Mainpage></Mainpage>
</div>
</BrowserRouter>
);
}
}
export default App;
The other thing that is weird is that it is loading the background of the page and styling that it is routing to when the button is not even pushed.
This is the main page.
class Mainpage extends Component {
render() {
return (
<div>
<header>
<nav>
<ul>
<li>
<Link exact to="/meettheteam">
This is a new Page
</Link>
</li>
</ul>
</nav>
</header>
<h1>
THE
<br />
BARBER
<br />
SHOP
</h1>
<p>
<img src={logo} alt="logo" />
<img src={facebookLogo} alt="logoFacebook" />
<img src={twitterLogo} alt="logoTwitter" />
#TheBarberShop
</p>
<ul>
<div className="schedule">
<li>SCHEDULE</li>
</div>
<div className="styles">
<li>STYLES</li>
</div>
<div className="meettheteam">
<li>MEET THE TEAM</li>
</div>
</ul>
<Switch>
<Route exact path="/meettheteam" component={MeetTheTeam} />
</Switch>
{/* <Route path="/stylesandprices" component={StylesAndPrices}/> */}
</div>
);
}
}
export default Mainpage;
Assuming you want the navigation portion of your main page to always render (to obviously allow navigation) then I have the following suggestions:
Move the header/nav to App component and render at the top of the router.
Move the Switch also to App and render your Mainpage and other page components in their own respective Route components, in decreasing specificity, i.e. "/pathA/b" listed before "/pathA".
Since the Switch matches and returns the first matching Route or Redirect, render the Mainpage route last as a default "home page".
If you want link highlighting (i.e. noticed the exact prop on the Link) then use NavLink as the Link component doesn't take this prop. Though, the exact prop here really only matters if you have nested routes that you don't want the link to appear active for
Changes
App
class App extends Component {
render() {
return (
<BrowserRouter>
<div className="App">
<header>
<nav>
<ul>
<li>
<Link to="/meettheteam">
This is a new Page
</Link>
</li>
</ul>
</nav>
</header>
<Switch>
<Route path="/meettheteam" component={MeetTheTeam} />
<Route path="/stylesandprices" component={StylesAndPrices} />
{/* other routes listing in decreasing specificity */}
<Route component={Mainpage} />
</Switch>
</div>
</BrowserRouter>
);
}
}
Mainpage
class Mainpage extends Component {
render() {
return (
<div>
<h1>
THE
<br />
BARBER
<br />
SHOP
</h1>
<p>
<img src={logo} alt="logo" />
<img src={facebookLogo} alt="logoFacebook" />
<img src={twitterLogo} alt="logoTwitter" />
#TheBarberShop
</p>
<ul>
<div className="schedule">
<li>SCHEDULE</li>
</div>
<div className="styles">
<li>STYLES</li>
</div>
<div className="meettheteam">
<li>MEET THE TEAM</li>
</div>
</ul>
</div>
);
}
}
Routes should be wrapped inside of a <Switch> component of react-router-dom
Right usage:
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import ComponentA from './componenta'
import ComponentB from './componentb'
function App() {
return (
<Router>
<Switch>
<Route path="/">
<ComponentA />
</Route>
<Route path="/componentb">
<ComponentB />
</Route>
</Switch>
</Router>
);
}
export default App
This example below would render first route and second route on top of each other, This is the similar way on how the code snippets of the question was structured. The first route was wrap with Switch while the second route was outside of Switch
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import ComponentA from './componenta'
import ComponentB from './componentb'
function App() {
return (
<Router>
<Switch>
<Route path="/">
<ComponentA />
</Route>
</Switch>
<Route path="/">
<ComponentB />
</Route>
</Router>
);
}
export default App;
Tips/Suggestion:
The best thing to do is to wrap all the Route's with Switch statement at the top level of the app hierarchy

Categories

Resources