Nested component in react-router is not rendering - javascript

I am just practicing how react-router works.
This is my App.js in which see message route
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';
import logo from './logo.svg';
import './App.css';
import styled, { css } from 'styled-components';
import About from './components/About';
import Home from './components/Home';
import Messages from './components/Messages';
const Ul = styled.ul`
list-style-type: none;
padding: 0;
margin: 0;
background-color: #282c34;
`;
function App() {
return (
<div className='App'>
<header className='App-header'>
<img src={logo} className='App-logo' alt='logo' />
<div>welcome to React</div>
</header>
<Ul>
<Li>
<NewLink to='/'>Home</NewLink>
</Li>
<Li>
<NewLink to='/messages'>Messages</NewLink>
</Li>
<Li>
<NewLink to='/about'>About</NewLink>
</Li>
</Ul>
<Container>
<Route exact path='/' component={Home} />
<Route exact path='/messages' component={Messages} />
<Route exact path='/about' component={About} />
</Container>
</div>
);
}
export default App;
when route switched to messages route messages get rendered
**This is messages Route **
import React from 'react';
import { Route } from 'react-router-dom';
import { Li, NewLink } from '../App';
import Message from './Message';
const Messages = ({ match }) => (
<div>
<ul>
{[...Array(5).keys()].map((n) => (
<Li key={n}>
<NewLink primary to={`${match.url}/${n + 1}`}>
Message {n + 1}
</NewLink>
</Li>
))}
</ul>
<Route path={`${match.url}/:id`} component={Message} />
</div>
);
export default Messages;
**This is message route but it is not rendering below Messages Route **
**can anyone please tell what is the problem **
import React from 'react';
const Message = ({ match }) => <h3>Message with ID {match.params.id}</h3>;
export default Message;

The issue here is the presence of exact prop on route /messages
Now when you have the exact prop on Route, unless the path matches exactly the Route is not rendered and hence the child Routes will never be evaluated.
A better practise is to use Switch component which renders the first matching Route and re-order the Routes so that prefix paths are the end
<Switch>
<Route path='/messages' component={Messages} /> // no exact props
<Route path='/about' component={About} />
<Route path='/' component={Home} /> // home route rendered at the end
</Switch>
Also on a sidenote, in order to define paths on Routes, you must use match.path instead of match.url

Related

how to create new react routes in a component according to the props?

I am trying to create a new react routes according to the props of components.
App.js routes the landing page to the Home component.
import "./App.css";
import Navbar from "./components/Navbar";
import Home from "./components/Home";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
function App() {
return (
<div>
<Navbar />
<Router>
<Routes>
<Route path="/" element={<Home />} />
</Routes>
</Router>
</div>
);
}
export default App;
I have service card file where I want to create new routes according to props.
Like for example
route = lorem -> /services/lorem
route = ipsum -> /services/ipsum
Servicecard looks like this
import React from "react";
import "../css/servicecard.css";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./Home";
const ServiceCard = ({ text, subClass, image, route }) => {
return (
<>
<div className={`card-container ${subClass}`} data-aos="fade-up">
<span className="card-title">{text}</span>
<img src={image} alt="service-icon" />
</div>
</>
);
};
export default ServiceCard;
i think you are talking about route params, here is an example:
export default function ParamsExample() {
return (
<Router>
<div>
<h2>Accounts</h2>
<ul>
<li>
<Link to="/netflix">Netflix</Link>
</li>
<li>
<Link to="/zillow-group">Zillow Group</Link>
</li>
<li>
<Link to="/yahoo">Yahoo</Link>
</li>
<li>
<Link to="/modus-create">Modus Create</Link>
</li>
</ul>
<Switch>
<Route path="/:param" children={<Child />} />
</Switch>
</div>
</Router>
);
}
and in the component child:
function Child() {
let { param } = useParams();
return (
<div>
<h3>ID: {param}</h3>
</div>
);
}

Nothing appears while using react router

I have a problem with react Router.
So i am building the nav of an website and when i'm doing the routes, nothing appears.
Would you help me please to see what i'm doing wrong?
The page stays white. Nothing appears, even the root doesnt see the homepage.
........................................................................................
Homepage:
import React from 'react';
import Navbar from '../allpages/navbar/Navbar';
import {
BrowserRouter as Router, Routes, Route
} from "react-router-dom";
import Contact from "../contact/Contact";
import About from "../about/About";
const Home = () => {
return (
<>
<Router>
<Navbar />
<Routes>
<Route path="/about" element={About} />
<Route path="/contact" element={Contact} />
<Route exact path="/" element={Home} />
</Routes>
</Router>
<h3>Home</h3>
</>
)
}
export default Home
Navbar:
import React from 'react';
import {
BrowserRouter as Link
} from "react-router-dom";
const Navbar = () => {
return (
<div>
<nav>
<ul>
<li>
<Link to="/home">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/contact">Contact</Link>
</li>
</ul>
</nav>
</div>
)
}
export default Navbar
main app:
import './App.css';
import Home from './components/home/Home'
function App() {
return (
<>
<Home />
</>
);
}
export default App;
contact:
import React from 'react';
const Contact = () => {
return (
<div>
<h3>Contact</h3>
</div>
)
}
export default Contact
About:
import React from 'react';
const About = () => {
return (
<div>
<h1>About</h1>
</div>
)
}
export default About
So besides this typo:
{ BrowserRouter as Link } // use just Link
which is inside Navbar.js
I would also use recommended approach by React-Router team. Which uses <Switch> component to wrap pages. You are using Routes instead, idk if this is even valid.
You can check this example: https://v5.reactrouter.com/web/example/basic
which is really similar to your code.
What versión is you using? You might be out of dated
<React.Suspense fallback={<p>Loading...</p>}>
<Routes>
<Route path="/*" element={<Outlet />}>
<Route path="informacion-financiera" element={<Financiera />} />
<Route path="derechos-de-autor" element={<Author />} />
<Route
</Route>
</Routes>
</React.Suspense>
```
What versión is you using? You might be out of dated
<React.Suspense fallback={<p>Loading...</p>}>
<Routes>
<Route path="/*" element={<Outlet />}>
<Route path="informacion-financiera" element={<Financiera />} />
<Route path="derechos-de-autor" element={<Author />} />
<Route
</Route>
</Routes>
</React.Suspense>
```
You have browserRouter as Link so yow links are not links

Nested routing in react.js is not giving the desired results

I want to display a custom component Resource.js whenever I click the linked text within a labCard.js component. On using the Outlet hook the Resource component is displayed within the lab Card and the Body.js component is not replaced. Body.js component is a collection of labCards component. My desire is to display the resource component in place of body component whenever I click Begin on the labCard component.
This is the App component
import React from 'react'
import { Routes, Route } from 'react-router-dom'
import Navbar from './components/Navbar'
import Home from './components/Home'
import Body from './components/Body'
import AboutUs from './components/AboutUs'
import GetHelp from './components/GetHelp'
import Footer from './components/Footer'
import Resource from './subComponents/Resource'
import './App.css';
function App() {
return (
<div>
<Navbar />
<Routes>
<Route path="/" element={ <Home /> } />
<Route path="/body/*" element={ <Body /> } >
<Route path="resource" element={ <Resource /> } />
</Route>
<Route path="/about" element={ <AboutUs /> } />
<Route path="/help" element={ <GetHelp /> } />
</Routes>
<Footer />
</div>
);
}
export default App;
This is the body Component
import React from 'react'
import LabCard from '../subComponents/LabCard'
import { data } from '../data'
import './Body.css'
export default function Body() {
const [labData, setLabData] = React.useState(data)
let labCardElements = labData.map(lab =>
<LabCard
key={lab.id}
labID={lab.id}
labType={lab.type}
labTitle={lab.title}
labResourceUrl={lab.resourceUrl}
/>)
return (
<section className='experiment-body-section'>
<h1 className='experiment-body--title'>Experiments</h1>
<p className='experiment-body--description'>Here are all the experiments</p>
<div className='experiment-body'>
{labCardElements}
</div>
</section>
)
}
This is the labCard component
import React from 'react'
import { Link } from 'react-router-dom'
import './Card.css'
export default function LabCard(props) {
return (
<div className='lab-card'>
<p className='lab-card--id'>{props.labType}</p>
<h2 className='lab-card--title'>{props.labTitle}</h2>
<div className="parent">
<div className='lab-card--overlay'></div>
<Link to="resource" className='lab-card-overlay--button'>Begin</Link>
</div>
</div>
)
}
If I'm understanding your question/issue correctly, it is that you don't want to render both the Body and Resource components at the same time.
In this case you should render Body on a nested index route. Both nested routes will be rendered into an Outlet by default on the parent route.
<Route path="/body">
<Route index element={<Body />} /> // <-- "/body"
<Route path="resource" element={<Resource />} /> // <-- "/body/resource"
</Route>

React router how do I include header links in the browser router without the header itself updating on redirect

I am fairly new to react but I have been told when making a website its good practice to have a layout component which holds the header, page content and footer however when using react router I want the header and footer to not update just the page content but if I add the links in the header outside the browserrouter tag I get a error saying they need to be inside but if i then include them inside the header updates along with the content..
In the header I have a navbar with links like this:
import React from 'react';
import { Link } from 'react-router-dom';
const Header = () => {
return(
<nav className="header-links">
<Link to="/" className="link">Home</Link>
<Link to="/about" className="link">About</Link>
<Link to="/contact" className="link">Contact Us</Link>
</nav>
);
}
export default HeaderNav;
Then in the layout file I include the header which has the links
import React from 'react'
import Header from './header/header'
import Footer from './footer/footer'
const PageLayout = ({children}) => {
return (
<div className="layout-wrapper">
<Header />
<main className="site-content">{children}</main>
<Footer />
</div>
);
}
export default PageLayout;
Then I also have a router file with my routes:
import React from 'react'
import HomePage from './pages/home'
import AboutPage from './pages/about'
import ContactPage from './pages/contact'
import {
Switch,
Route,
BrowserRouter
} from 'react-router-dom';
const Routes = () => (
<BrowserRouter>
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/about" component={AboutPage} />
<Route exact path="/contact" component={ContactPage} />
</Switch>
</BrowserRouter>
);
export default Routes;
The problem that I am having is if in the layout.js I only wrap the page content in the browserrouter tag then I get a error saying my links need to be inside this BUT if I then wrap the header, page content and footer in the browserrouter then they all update when a link is clicked so I am struggling with how do I include the links in the browserrouter without the header updating?
For instance:
import React from 'react'
import Header from './header/header'
import Footer from './footer/footer'
const PageLayout = ({children}) => {
return (
<div className="layout-wrapper">
<Routes>
<Header />
<main className="site-content">{children}</main>
<Footer />
<Routes />
</div>
);
}
export default PageLayout;
I might be totally off base here, but I'm pretty sure you want something like this:
<BrowserRouter>
<Header/>
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/about" component={AboutPage} />
<Route exact path="/contact" component={ContactPage} />
</Switch>
<Footer />
</BrowserRouter>

<BrowserRouter> Does not remove hashbang from route

There is a #/ (hashbang) in my react route...
searching online yeilds covering <Route> with the new <BrowserRouter> will fix the problem
import React, { Component } from 'react';
import './App.scss';
import { observer } from 'mobx-react';
import { Header } from './components/Header'
import { Footer } from './components/Footer';
import { Route , BrowserRouter , Switch } from 'react-router-dom';
import MainState from './components/appset/MainState';
import HomePage from './components/HomePage';
import { TestContent } from './components/TestContent';
import { Account } from './components/Account';
import { TokenList } from './components/TokenList';
import { TokenPage } from './components/TokenPage';
import ErrorPage from './components/ErrorPage';
class Layout extends Component {
render() {
return (
<div id="bodyWheel" className={`App ${MainState.currentTheme} ${MainState.currentLang}`}>
<Header />
<div id="App-intro" className={this.state.resolutionHeight}>
<div className="container">
<div className="layout-main">
<BrowserRouter>
<Route path="/" exact component={HomePage} />
<Route path="/test" component={TestContent} />
<Route path="/account/:id" exact component={Account} />
<Route path="/token" exact component={TokenPage} />
<Route path="/token/:id" exact component={TokenList} />
<Route path="/operation/:id" exact component={HomePage}/>
<Route path="/error/:id" exact component={ErrorPage} />
</BrowserRouter>
</div>
</div>
</div>
<Footer />
</div>
);
}
}
export default Layout;
It adds #/ by itself at the end of every route for example:
www.foo.com/account/tera
becomes
www.foo.come/account/tera#/
<BrowserRouter> did nothing at all.
Will building and uploading to a webserver instead of running on 'npm start' fix the problem?
(edit:) turns out <BrowserRouter> works but something just keeps adding#/to the end of my routes the routs without#/` works just fine
fix is in the <BrowserRouter> edit to <BrowserRouter basename="">
and cover the main div
<BrowserRouter basename="">
<div id="bodyWheel" className={`App ${MainState.currentTheme} ${MainState.currentLang}`}>
....
</div>
</BrowserRouter>
fixed all the routing problems!

Categories