I'm trying to create a website in react and am using router-dom to have the correct url showing.
I have a navbar that links to an about page using Link to="" and then using Switch and Route to display the component for the correct path, but it doesn't work.
Not sure if I missed anything here but I can't manage to display any components.
This is my PageContainer
import React from "react";
import { Route, Switch } from "react-router-dom";
import Alphabet from "./Alphabet";
import About from "./About";
export default class PageContainer extends React.Component {
render() {
return (
<section className="pagecontainer">
<Switch>
<Route exact path="/omoss">
<About />
</Route>
<Route exact path="/">
<Alphabet />
</Route>
</Switch>
</section>
);
}
}
This is my navbar
import React from "react";
import { Link } from "react-router-dom";
export default class Navbar extends React.Component {
render() {
return (
<section>
<section className="navbar">
<Link to="/">Hem</Link>
<Link to="/omoss">OM OSS</Link>
</section>
</section>
);
}
}
UPDATE:
Removed BrowserRouter from both components above.
Changed App.js to below.
App.js
import React from "react";
import "./App.css";
import { BrowserRouter } from "react-router-dom";
import Navbar from "./components/Navbar";
import PageContainer from "./components/PageContainer";
function App() {
return (
<BrowserRouter>
<section className="App">
<Navbar />
<PageContainer />
</section>
</BrowserRouter>
);
}
export default App;
Still not working though. The url changes but the components doesn't show.
UPDATE 2
Think I solved it when I removed two other components that where showing in Switch inside PageContainer but weren't in a Route. I had removed them before uploading here but forgot them in my code
You have two individual <BrowserRouter /> components, each with its own state. I suggest that you move the <BrowserRouter /> component to a common ancestor of both <Navbar /> and <PageContainer /> so that they can share the same history object.
For example, remove the BrowserRouter from your components and place it higher in the component hierarchy. Now, both <Navbar /> and <PageContainer /> are in the scope of the same <BrowserRouter />
function App() {
return (
<BrowserRouter>
<Navbar />
<PageContainer />
</BrowserRouter>
);
}
Try to add BrowserRouter in App.js
import React from "react";
import "./App.css";
import { BrowserRouter } from "react-router-dom";
import Navbar from "./components/Navbar";
import PageContainer from "./components/PageContainer";
function App() {
return (
<BrowserRouter>
<section className="App">
<PageContainer />
<Navbar />
</section>
</BrowserRouter>
);
}
export default App;
Related
I have been receiving white blank pages when trying to create multiple pages within my app and I have been using the router-dom to try and fix this but still can't understand why. Here is my code with Home and Navigation js being inside a components folder in the src directory and App.js just inside the src directory.
App.js
import React, { Component } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import Home from './components/Home';
import Glazing from './components/Glazing';
import Navigation from './components/Navigation';
class App extends Component {
render() {
return (
<BrowserRouter>
<div>
<Navigation />
<Route path="/" component={Home} exact/>
<Route path="/glazing" component={Glazing}/>
</div>
</BrowserRouter>
);
}
}
export default App;
Nav.js
import React from 'react';
import { NavLink } from 'react-router-dom';
const Navigation = () => {
return (
<div>
<NavLink to="/">Home</NavLink>
<NavLink to="/glazing">Glazing</NavLink>
</div>
);
}
export default Navigation;
Home.js
import React from "react";
import logo from '../logo.svg';
import './Home.css';
import "#fontsource/dm-sans";
function home() {
return (
<div className="Home">
<header className="Home-header">
<h1>EPC RATING PREDICTOR</h1>
</header>
<button> GET STARTED</button>
</div>
);
}
export default Home;
If you are using react-router-dom#6 then there are a couple things you need to address.
The Switch component was replaced by the Routes component and all Route components must be wrapped/rendered directly by Routes, or another Route component in the case of nesting routes.
The Route component API changed; gone are the component, and render and children function props, all replaced by a single element prop taking a ReactNode, a.k.a. JSX, value.
Example:
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Home from './components/Home';
import Glazing from './components/Glazing';
import Navigation from './components/Navigation';
class App extends Component {
render() {
return (
<BrowserRouter>
<div>
<Navigation />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/glazing" element={<Glazing />} />
</Routes>
</div>
</BrowserRouter>
);
}
}
See the Upgrading from v5 guide for other changes.
App.js code-
import React from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";
import { Container } from "react-bootstrap";
import Header from "./components/Header";
import Footer from "./components/Footer";
import HomeScreen from "./screens/HomeScreen";
const App = () => {
return (
<Router>
<Header />
<main className='py-3'>
<Container>
<HomeScreen />
</Container>
</main>
<Footer />
</Router>
);
};
export default App;
My app.js was like this and everything was working fine. But after that I added Route tag and the code become like this
import React from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";
import { Container } from "react-bootstrap";
import Header from "./components/Header";
import Footer from "./components/Footer";
import HomeScreen from "./screens/HomeScreen";
const App = () => {
return (
<Router>
<Header />
<main className='py-3'>
<Container>
<Route exact path='/' component={HomeScreen} />
</Container>
</main>
<Footer />
</Router>
);
};
export default App;
But after adding Route, HomeScreen is not rendering?
Can anybody tell me why this is happening?
In react-router-dom v6 the Route component must be rendered into a Routes component, and the routed components are rendered on the element prop as a ReactElement (a.k.a. JSX) since the component, and render and children function props no longer exist.
import React from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import { Container } from "react-bootstrap";
import Header from "./components/Header";
import Footer from "./components/Footer";
import HomeScreen from "./screens/HomeScreen";
const App = () => {
return (
<Router>
<Header />
<main className='py-3'>
<Container>
<Routes>
<Route path='/' element={<HomeScreen />} />
</Routes>
</Container>
</main>
<Footer />
</Router>
);
};
I am having an issue with react router as my url is getting updated on clicking on it but the page is not getting rendered but when I reload it at that specific url then it renders the content whereas I want it to be rendered as soon as I click on the link
this is my App.js
import React from 'react';
import Nav from './Nav';
import { BrowserRouter as Router ,Switch, Route} from 'react-router-dom';
import About from './About'
function App() {
return (
<>
<Router>
<Nav/>
<Switch>
<Route exact path='/about' render={About} />
</Switch>
</Router>
</>
);
}
export default App;
This is my Nav.js
import React from "react";
import {BrowserRouter as Router , Link } from "react-router-dom";
import './App.css';
function Nav(){
return(
<Router>
<nav>
logo
<Link to="/about">
About
</Link>
<Link to='/shop'>
shop
</Link>
</nav>
</Router>
)
}
export default Nav
this is my About.js
import React from "react";
function About(){
return(
<div>
About Page
</div>
)
}
export default About
You should either wrap the App component with BrowserRouter or, wrap the App component with Router component that accepts a history prop.
Index.js
import { BrowserRouter } from 'react-router-dom'
ReactDOM.render(<BrowserRouter>
<App />
</BrowserRouter>,document.getElementById("root"));
App.js
import React from 'react';
import Nav from './Nav';
import { BrowserRouter as Router ,Switch, Route} from 'react-router-dom';
import About from './About'
function App() {
return (
<>
<Nav/>
<Switch>
<Route exact path='/about'>
<About/>
</Route>
</Switch>
</>
);
}
export default App;
Nav.js
import React from "react";
import {BrowserRouter as Router , Link } from "react-router-dom";
import './App.css';
function Nav(){
return(
<nav>
logo
<Link to="/about">
About
</Link>
<Link to='/shop'>
shop
</Link>
</nav>
)
}
export default Nav
Since, Nav.js and other components using Routes are wrapped within the app component which is further wrapped within BrowserRouter in index.js, you don't need to include Router in each component having Route or Link components.
I have a router set up in my App.js as follows:
import React from 'react';
import { BrowserRouter as Router, Route, Switch, Redirect } from 'react-router-dom';
import NavBar from './nav-bar';
import Landing from './landing-page';
import Dashboard from './dashboard';
import Analysis from './analysis';
import '../style.scss';
const App = (props) => {
return (
<Router>
<NavBar />
<Switch>
<Route exact path="/" component={Landing} />
<Route path="/dashboard/:prodID/search" component={Dashboard} />
<Redirect from="/dashboard/:prodID" to="/dashboard/:prodID/search" />
<Route path="/dashboard/:prodID/analyze" component={Analysis} />
<Route component={() => (
<div id="error">
<h1>404 ERROR</h1>
<h2>Page not found</h2>
</div>
)}
/>
</Switch>
</Router>
);
};
export default App;
and my NavBar component is set up as follows:
import React, { Component } from 'react';
import { NavLink, withRouter } from 'react-router-dom';
import { Navbar, Nav } from 'react-bootstrap';
import '../style.scss';
class NavBar extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<Navbar id="nav-bar" bg="dark" variant="dark">
<Navbar.Brand href="/">
My Project
</Navbar.Brand>
<Navbar.Collapse id="responsive-navbar-nav" className="justify-content-end">
<Nav>
<NavLink to="/dashboard/:prodID/search">Search</NavLink>
<NavLink to="/dashboard/:prodID/analyze">Analyze</NavLink>
</Nav>
</Navbar.Collapse>
</Navbar>
);
}
}
export default withRouter(NavBar);
I have two things that I'm trying to figure out:
I want to be able to access the prodID route param within my NavBar component so that when a user clicks on the route, it will take the valid prodID and render the route correctly.
I want to only display the NavLinks in NavBar if the user is on a route that has the prodID param. If they're on the home route / for example, the links wouldn't show up. But if they're on the route /dashboard/[valid prodID]/search, the links would show up.
How do I go about implementing this? I've looked at other posts on SO dealing with route params and nav bars, but none of them have answered my question. Any help is appreciated.
I believe you would have to move your navbar under each of the routes, so that it can be re-rendered and grab the correct params when the path changes.
In order to achieve it, you can create the Layout component which will wrap the component you pass and add a navbar to it:
// Layout.jsx
import React from "react";
import NavBar from './nav-bar';
export const Layout = () => {
return (
<div>
<Navbar />
<div>{children}</div>
</div>
);
};
Then in your App, you can wrap each component within the routes with the Layout component like so
// App.jsx
import React from "react";
import {
BrowserRouter as Router,
Route,
Switch,
Redirect
} from "react-router-dom";
import NavBar from "./nav-bar";
import Landing from "./landing-page";
import Dashboard from "./dashboard";
import Analysis from "./analysis";
import { Layout } from "./Layout";
import "../style.scss";
const App = props => {
return (
<Router>
<Switch>
<Route exact path="/">
<Layout>
<Landing />
</Layout>
</Route>
<Route path="/dashboard/:prodID/search">
<Layout>
<Dashboard />
</Layout>
</Route>
<Redirect from="/dashboard/:prodID" to="/dashboard/:prodID/search" />
<Route path="/dashboard/:prodID/analyze">
<Layout>
<Analysis />
</Layout>
</Route>
<Route
component={() => (
<div id="error">
<h1>404 ERROR</h1>
<h2>Page not found</h2>
</div>
)}
/>
</Switch>
</Router>
);
};
export default App;
This approach would help you achieve your second goal. Since the navbar is now nested under each route, you can easily fetch the params from the path and conditionally render the links, like so:
// NavBar.jsx
import React from "react";
import { NavLink, useParams } from "react-router-dom";
import { Navbar, Nav } from "react-bootstrap";
import "../style.scss";
const NavBar = () => {
const { prodID } = useParams();
return (
<Navbar id="nav-bar" bg="dark" variant="dark">
<Navbar.Brand href="/">My Project</Navbar.Brand>
<Navbar.Collapse
id="responsive-navbar-nav"
className="justify-content-end"
>
<Nav>
{prodID && (
<NavLink to={`/dashboard/:${prodID}/search`}>Search</NavLink>
)}
{prodID && (
<NavLink to={`/dashboard/:${prodID}/analyze`}>Analyze</NavLink>
)}
</Nav>
</Navbar.Collapse>
</Navbar>
);
};
export default NavBar;
I haven't tested it, but it should help you with your issues.
I am trying to use the react-dom-router package within my React app but I am not being "redirected" successfully to the component. It only works when I refresh the page or access via the URL.
This is my App.js:
import React, { Component } from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";
import NavMenu from "./components/NavMenu/NavMenu";
import Contact from "./components/Contact/Contact";
import Home from "./components/Home/Home";
class App extends Component {
render() {
return (
<Router>
<div>
<NavMenu />
<Route exact path='/' component={Home} />
<Route path='/contact' component={Contact} />
</div>
</Router>
);
}
}
export default App;
This is my NavbarMenu component's code:
import React, { Component } from "react";
import { Navbar, Nav } from "react-bootstrap";
import { BrowserRouter as Router, Link } from "react-router-dom";
class NavMenu extends Component {
render() {
return (
<Router>
<Navbar bg='light' expand='lg'>
<Navbar.Brand>Company name</Navbar.Brand>
<Nav className='mr-auto'>
<Nav.Link>
<Link to='/'>Home</Link>
</Nav.Link>
<Nav.Link>
<Link to='/contact'>Contact</Link>
</Nav.Link>
</Nav>
</Navbar>
</Router>
);
}
}
export default NavMenu;
I guess the code for Home & Contact components aren't relevant.
So, when I visit my React app default page http://localhost:3000/ I see the navbar with their links. But when I click in a link, the URL changes but nothing happens until I refresh the page or access from the URL.
I was following this tutorial to get this done. Any ideas?
Its s because you are using Router twice, first in App.js and then again in NavMenu. We only need to wrap the App container (entry point) with Router.
Remove the <Router> from NavMenu component. Write it like this:
import React, { Component } from "react";
import { Navbar, Nav } from "react-bootstrap";
import { Link } from "react-router-dom";
class NavMenu extends Component {
render() {
return (
<Navbar bg='light' expand='lg'>
<Navbar.Brand>Company name</Navbar.Brand>
<Nav className='mr-auto'>
<Nav.Link>
<Link to='/'>Home</Link>
</Nav.Link>
<Nav.Link>
<Link to='/contact'>Contact</Link>
</Nav.Link>
</Nav>
</Navbar>
);
}
}
export default NavMenu;