React Router loads URL in address bar but doesn't load component - javascript

Codesandbox link here.
When a user clicks on a link, it should load the component in '/details'. However on click, it does load /details in the address bar but the component doesn't actually load. It only loads on going separately to /details manually in the address bar.
Routes.js
const Routes = () => {
return (
<BrowserRouter>
<Switch>
<Route exact path="/" component={App} />
<Route exact path="/details" component={MachineDetail} />
</Switch>
</BrowserRouter>
);
};
MachineCard.js
export default function MachineCard({ image, title, weight, power }) {
return (
<>
<div className="col-lg-4">
<div className="card">
<Router>
<Link to="/details">
<img className="img-fluid" src={image} alt={title} />
<h2>{title}</h2>
</Link>
</Router>
<p>Operating weight: {weight}</p>
<p>Power: {power}</p>
</div>
</div>
</>
);
}
Any idea why it won't load the '/details' component in the browser?

This issue is that you have multiple routers in your app, but you only need one. Since you already have the router defined in your index file, you can go ahead and remove it from MachineCard.js.
Your MachineCard.js component can therefore be simplified to this:
export default function MachineCard({ image, title, weight, power }) {
return (
<>
<div className="col-lg-4">
<div className="card">
<Link to="/details">
<img className="img-fluid" src={image} alt={title} />
<h2>{title}</h2>
</Link>
<p>Operating weight: {weight}</p>
<p>Power: {power}</p>
</div>
</div>
</>
);
}

I think your problem is incorrect naming. In your route files you are using MachineDetail but you are exporting MachineCard.

Related

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 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 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 routing to endpoint but not rendering content

I can route to another endpoint, but the component content only appears on manual refresh.
I've seen this question asked here, here, and I've been checking out the reactrouter docs, amongst others. The solution always seems to be "add withRouter" or "make sure you're wrapping it in Router. I've done those things, but sadly got no where.
Here's the code:
App.js
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
function App() {
return (
<Router>
<Provider store={store}>
<div className="App">
<NavBar />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/account" component={Account} />
</Switch>
</div>
</Provider>
</Router>
);
}
NavBar.js
import { BrowserRouter as Router, Link } from "react-router-dom";
import { withRouter } from "react-router";
function NavBar() {
return (
<Router>
<div className="navbar">
<h3>Connectory</h3>
<div className="buttons-container">
<Link>
<button>Settings</button>
</Link>
<Link to="/account"> // successfully redirects to /account, but doesn't render Account page content until refresh
<button>Account</button>
</Link>
</div>
</div>
</Router>
);
}
export default withRouter(NavBar);
EDIT: After comment suggestions, here's a code sandbox link and here;s the Account.js page:
import React from "react";
export default function Account() {
return (
<div>
<h3>This is the Account page</h3>
</div>
);
}
The Problem here is that, in your Navbar.js, you are re-setting your Routes again when they are already set in App.js.
<Switch>
<Route exact path="/" component={Home} />
<Route path="/account" component={Account} /> // Route for Applicatin set here
</Switch>
You do not need to do that again in. Check here.
https://codesandbox.io/s/gracious-germain-7fyry?file=/src/Navbar.js
Your Nabar should look like:
function NavBar() {
return (
<div className="navbar">
<h3>Connectory</h3>
<div className="buttons-container">
<Link to="/">
<button>Settings</button>
</Link>
<Link to="/account">
<button>Account</button>
</Link>
</div>
</div>
);
}
Hi i found a bug in your code and that's the reason because is not working.
in this component you are injecting the Router to the rest of the app.
function App() {
return (
<Router>
<div className="App">
<NavBar />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/account" component={Account} />
</Switch>
</div>
</Router>
);
}
in this one you are injecting again the Router. That's why is not working you just have to remove the Router from de Navbar and it will work properly.
function NavBar() {
return (
<Router>
<div className="navbar">
<h3>Connectory</h3>
<div className="buttons-container">
<Link>
<button>Settings</button>
</Link>
<Link to="/account">
<button>Account</button>
</Link>
</div>
</div>
</Router>
);
}
like this
function NavBar() {
return (
<div className="navbar">
<h3>Connectory</h3>
<div className="buttons-container">
<Link>
<button>Settings</button>
</Link>
<Link to="/account">
<button>Account</button>
</Link>
</div>
</div>
);
}

Categories

Resources