I am trying to make a Navbar but the isn't re-directing to the given page. If I click any of the links in the Navbar, it would change the path in the url bar but won't re-direct to that page. I am not sure if I am missing anything. When I replace it with the tags, it works perfectly.
Navbar.js
import React from "react";
import { BrowserRouter as Router, Link, Switch } from "react-router-dom";
const Navbar = () => {
return (
<Router>
<Switch>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/articles">Articles</Link>
</li>
<li>
<Link to="/articles-all">All articles</Link>
</li>
</ul>
</nav>
</Switch>
</Router>
);
};
export default Navbar;
App.js
import React from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";
import './App.css'
//pages
import Home from "./Pages/Home";
import About from "./Pages/About";
import Articles from "./Pages/Articles";
import ArticlesList from "./Pages/ArticlesList";
//components
import Navbar from './components/Navbar';
const App = () => {
return (
<div>
<Navbar/>
<Navigation />
</div>
);
};
export default App;
const Navigation = () => {
return (
<Router>
<div id="page-body">
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/articles" component={Articles} />
<Route path="/articles-all" component={ArticlesList} />
</div>
</Router>
);
};
Since you define the Router within Navigation and another one in Navbar your Links are not able to communicate to the Router Component in Navigation as they just communicate to their nearest parent Router component
You must you use a single Router instance to be able to perform seemless navigation within your App. Also a Switch component is not needed with Links but with Route
const App = () => {
return (
<Router>
<Router component={Navbar}/> // rendered as default route so that they receive router props
<Router component={Navigation} />
</Router>
);
};
export default App;
const Navigation = () => {
return (
<div id="page-body">
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/articles" component={Articles} />
<Route path="/articles-all" component={ArticlesList} />
</div>
);
};
const Navbar = () => {
return (
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/articles">Articles</Link>
</li>
<li>
<Link to="/articles-all">All articles</Link>
</li>
</ul>
</nav>
);
};
export default Navbar;
Here's a working codesandbox URL https://codesandbox.io/s/frosty-black-3i8hp?file=/src/App.js
You were wrapping links with browserRouter and Switch. These APIs are intended to wrap Routes only.
So, It wasn't able to communicate well with your react app.
Related
Trying to create an about page for a website im working on, I found this solution on Stack but it does not work for me. I was using an outdated tutorial for my original code, this is my current code:
About.js:
import React from "react";
import { Link, Route, useMatch } from "react-router-dom";
import SinglePage from "./SinglePage";
const About = () => {
//const match = useMatch('/');
return (
<div className="about__content">
<ul className="about__list">
<li>
<Link to={'about-app'}>About App</Link>
</li>
<li>
<Link to={'about-author'}>About Author</Link>
</li>
</ul>
<Route path={':slug'}>
<SinglePage />
</Route>
</div>
);
};
export default About;
Index.js where I am rendering the component:
import React from "react";
import ReactDOM from "react-dom";
import TodoContainer from "./functionBased/components/TodoContainer"; // Component file
import "./functionBased/App.css"; // Style sheet
import { HashRouter as Router, Routes, Route } from "react-router-dom"; // Router file
import About from "./functionBased/pages/About";
import NotMatch from "./functionBased/pages/NotMatch";
ReactDOM.render(
<React.StrictMode>
<Router>
<Routes>
<Route exact path="/" element={<TodoContainer />} />
<Route path="/about/*" element={<About />} />
<Route path="*" element={<NotMatch />} />
</Routes>
</Router>
</React.StrictMode>,
document.getElementById("root")
);
Issues
The About component is directly rendering a Route component. The Route component can only be rendered by a Routes component or another Route component as a nested route.
The react-router-dom#6 Route components render their content on the element prop.
Solution
Import the Routes component and wrap the descendent Route component rendered by `About.
Render SinglePage on the route's element prop.
Example:
import React from "react";
import { Link, Routes, Route } from "react-router-dom";
import SinglePage from "./SinglePage";
const About = () => {
return (
<div className="about__content">
<ul className="about__list">
<li>
<Link to="about-app">About App</Link>
</li>
<li>
<Link to="about-author">About Author</Link>
</li>
</ul>
<Routes>
<Route path=":slug" element={<SinglePage />} />
</Routes>
</div>
);
};
export default About;
Alternative
You could alternatively move the SinglePage route out to the main router as a nested route (instead of where it is as a descendent route).
Example:
import React from "react";
import { Link, Outlet } from "react-router-dom";
import SinglePage from "./SinglePage";
const About = () => {
return (
<div className="about__content">
<ul className="about__list">
<li>
<Link to="about-app">About App</Link>
</li>
<li>
<Link to="about-author">About Author</Link>
</li>
</ul>
<Outlet />
</div>
);
};
export default About;
...
<Router>
<Routes>
<Route path="/" element={<TodoContainer />} />
<Route path="/about" element={<About />}>
<Route path=":slug" element={<SinglePage />} />
</Route>
<Route path="*" element={<NotMatch />} />
</Routes>
</Router>
You are defining the routes with /about/* and accessing them with about-something which does not exist at all, add \about\author in to for Link.
If I type in a URL that doesn't exist in my app, it sends me to a custom 404 Not Found page.
However, when I wrap my Navbar with <User.Provider value={value}> .... </User.Provider>, the 404 Not Found component appears on all pages.
Basically, I don't want the NoMatch component to appear on all other pages, only when a url does not exist/match with my app's navbar.
So if I type in localhost:5000/this-does-not-exist-12345212wergdv
it should take me to the custom component, NoMatch.
Code sandbox link.
https://codesandbox.io/s/delicate-sea-b2r96?file=/src/App.js
Anyone know how I can solve this? Thanks for any help.
My code below.
UserContext.jsx code
import React from "react";
export const User = React.createContext(null);
Home.jsx code
import React from "react";
import {User} from "../auth/UserContext";
const Home = props => {
const {user} = React.useContext(User);
return (
<div>
<h4>This is Home page</h4>
<h4>User: {JSON.stringify({user})}</h4>
</div>
);
}
export default Home;
Navbar.jsx code
import React from "react";
import {
BrowserRouter as Router,
Route,
Link,
Switch,
Redirect,
useLocation,
useHistory
} from "react-router-dom";
import {User} from "../auth/UserContext";
import Home from "../pages/Home";
const Navbar = React.memo(props => {
const [user, setUser] = React.useState(null);
const value = React.useMemo(() => ({user, setUser}), [user, setUser]);
const history = useHistory();
return (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/old-match">Old Match, to be redirected</Link>
</li>
<li>
<Link to="/will-match">Will Match</Link>
</li>
<li>
<Link to="/will-not-match">Will Not Match</Link>
</li>
<li>
<Link to="/also/will/not/match">Also Will Not Match</Link>
</li>
</ul>
<Switch>
<User.Provider value = {value}>
<Route exact path="/">
<Home />
</Route>
<Route path="/old-match">
<Redirect to="/will-match" />
</Route>
<Route path="/will-match">
<WillMatch />
</Route>
<Route path="*">
<NoMatch />
</Route>
</User.Provider>
</Switch>
</div>
</Router>
);
})
function WillMatch() {
return <h3>Matched!</h3>;
}
function NoMatch() {
let location = useLocation();
return (
<div>
<h3>
No match for <code>{location.pathname}</code>
</h3>
</div>
);
}
export default Navbar;
App.jsx page
import React from "react";
import Navbar from "./components/Navbar";
export default function App(props) {
return (
<div>
<Navbar/>
</div>
);
}
The explanation is that the Switch component looks only at its direct children for the path property regardless of whether or not they are Routes.
In this case, since the direct child of Switch is User.Provider with no path property the switch will always just render that child (a switch will always render at least one child).
Now the children of User.Provider will be rendered, and the Switch will no longer have any bearing. This means now that the <Route path="*" /> will ALWAYS render like you are seeing.
Solution:
The solution is to just move the location of the User.Provider to surround the Switch component.
const Navbar = React.memo(props => {
const [user, setUser] = React.useState(null);
const value = React.useMemo(() => ({user, setUser}), [user, setUser]);
const history = useHistory();
return (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/old-match">Old Match, to be redirected</Link>
</li>
<li>
<Link to="/will-match">Will Match</Link>
</li>
<li>
<Link to="/will-not-match">Will Not Match</Link>
</li>
<li>
<Link to="/also/will/not/match">Also Will Not Match</Link>
</li>
</ul>
<User.Provider value = {value}>
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/old-match">
<Redirect to="/will-match" />
</Route>
<Route path="/will-match">
<WillMatch />
</Route>
<Route path="*">
<NoMatch />
</Route>
</Switch>
</User.Provider>
</div>
</Router>
);
})
when i use link on my navbar component it changes the url but does not change the component, but it changes component when i reload,when i put link in main app.js it routes perfectly
app.js
import './App.css';
import Navbar from './Navbar/Navbar'
import About from './About/About'
import { Route, Link, BrowserRouter as Router ,Switch} from 'react-router-dom'
function App() {
return (
<div>
<Navbar/>
<Router>
<Link to="/about">about</Link>
<Switch>
<Route exact path="/about">
<About/>
</Route>
</Switch>
</Router>
</div>
);
}
export default App;
navbar.js
import React from 'react'
import './Navbar.css'
import { Link, Router, BrowserRouter} from 'react-router-dom';
function Navbar() {
return (
<div>
<nav className="navbar">
<div>
<h1 className="nav_text">ExportGrains</h1>
</div>
<ul className="nav_ul">
<BrowserRouter>
<Link to="/about">about</Link>
<li id="nav_li">HOME</li>
<li id="nav_li">PRODUCTS</li>
<li id="nav_li">ABOUT</li>
<li id="nav_li">CONTACT</li>
</BrowserRouter>
</ul>
</nav>
</div>
)
}
export default Navbar
about.js
import React from 'react'
function About() {
return (
<div>
<h1>about page</h1>
</div>
)
}
export default About;
it would be very kind if you can help me with it
It should be
import About from "...."
....
....
<Route path="/about" exact component={About} />
You should use one single Router for all your routes. The problem is that navbar is using different router and your other components are inside another router. So remove the router inside navbar and use single router inside your app component.
Also you can add Navbar as default route and put it at the end of the switch so that it matches when none of the above routes are matching.
function App() {
return (
<Router>
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/">
<Navbar />
</Route>
</Switch>
</Router>
);
}
Switch renders the first child <Route> or <Redirect> that matches the
location.
function Navbar() {
return (
<div>
<nav className="navbar">
<div>
<h1 className="nav_text">ExportGrains</h1>
</div>
<ul className="nav_ul">
<Link to="/about">about</Link>
<li id="nav_li">HOME</li>
<li id="nav_li">PRODUCTS</li>
<li id="nav_li">ABOUT</li>
<li id="nav_li">CONTACT</li>
</ul>
</nav>
</div>
);
}
My folder structure
reactdemo
|------------>public
|------------>src
|------->Component
|------->index.js
<-------------index.js------------>
import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';
import ReactDOM from 'react-dom';
import Header from './Component/Header';
import Footer from './Component/Footer';
import Content from './Component/Content';
import About from './Component/about';
import Contact from './Component/Contact';
import JSON from './Component/db.json';
class App extends React.Component {
state = {
items:JSON
}
render() {
// console.log(this.state.items)
return (
<div>
<Header/>
<Content list={this.state.items} />
<Footer />
</div>
);
}
}
ReactDOM.render(<App/>, document.getElementById('root'));
<---------Header Component------------->
import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';
//Component
import About from './about.js';
import Contact from './Contact.js';
class Header extends React.Component {
render() {
return (
<Router>
<div>
<nav className="navbar navbar-expand-sm bg-dark navbar-dark">
<ul className="navbar-nav">
<li className="nav-item">
<Link to="/">Home</Link>
</li>
<li className="nav-item">
<Link to="/about">About</Link>
</li>
<li className="nav-item">
<Link to="/contact">Contact</Link>
</li>
</ul>
</nav>
<Switch>
<Route path='/About' Component={About} />
<Route path='/Contact' Component={Contact} />
</Switch>
</div>
</Router>
);
}
}
export default Header;
<----------Content---------------->
import React from 'react';
const Content =(props) => {
console.log(props)
const test = props.list.map((list) => {
return (
<div key={list.id}>
<h4>{list.title}</h4>
<p>{list.feed}</p>
</div>
)
}
)
return (
<div>
{test}
</div>
)
}
export default Content;
<---------footer.js---------->
import React from 'react';
class Footer extends React.Component {
render() {
return (
<div className="text-center">
<p>Posted by: Hege Refsnes</p>
<p>Contact information: <a href="mailto:someone#example.com">
someone#example.com</a>.</p>
</div>
);
}
}
export default Footer;
<---------about---------->
import React, { Component } from 'react';
import { render } from 'react-dom';
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';
class About extends Component {
render() {
return (
<div>
<h2>About</h2>
</div>
);
}
}
export default About;
<------------Contact---------->
import React, { Component } from 'react';
import { render } from 'react-dom';
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';
class Contact extends Component {
render() {
return (
<div>
<h2>Contact</h2>
</div>
);
}
}
export default Contact;
<-----------End of Code-------->
I'm new to react and trying to implement react router. But I'm facing an issue- whenever I click on About and Contact link, the url changes in the browser, but the contents don't show in the browser. I have created separate contents for both "about" and "contact" inside the Components folder.Also, I'm using Sublime text 3 and using Babel for ES-6 as plugin but it's showing syntax error.I have also attached a screenshot for showing the issue
You write your component attribute with first letter uppercase, so Component should be component:
So instead of:
<Route path='/About' Component={About} />
<Route path='/Contact' Component={Contact} />
You should have:
<Route path='/About' component={About} />
<Route path='/Contact' component={Contact} />
import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';
//Component
import About from './about.js';
import Contact from './Contact.js';
class Header extends React.Component {
render() {
return (
<Router>
<div>
<nav className="navbar navbar-expand-sm bg-dark navbar-dark">
<ul className="navbar-nav">
<li className="nav-item">
<Link to="/">Home</Link>
</li>
<li className="nav-item">
<Link to="/about">About</Link>
</li>
<li className="nav-item">
<Link to="/contact">Contact</Link>
</li>
</ul>
</nav>
<Switch>
<Route path='/About' component={About} />
<Route path='/Contact' component={Contact} />
</Switch>
</div>
</Router>
);
}
}
export default Header;
It's not a deal breaker to use the path prop value to uppercase, because it's not case sensitive by default, but is recommended to have the <Route> path props the same you define on the <Link>, in case you have a prop like sensitive defined on the <Route> element.
In this case your final piece of code should look like this:
<Route path='/about' component={About} />
<Route path='/contact' component={Contact} />
You can read more about this in the docs here.
the Link paths are defined as /about and /contact, where the Route paths are /About and /Contact, notice the uppercase first character and hence it doesn't match, also Route accepts a lower case component prop and not Component
<Router>
<div>
<nav className="navbar navbar-expand-sm bg-dark navbar-dark">
<ul className="navbar-nav">
<li className="nav-item">
<Link to="/">Home</Link>
</li>
<li className="nav-item">
<Link to="/about">About</Link>
</li>
<li className="nav-item">
<Link to="/contact">Contact</Link>
</li>
</ul>
</nav>
<Switch>
<Route path='/about' component={About} />
<Route path='/contact' component={Contact} />
</Switch>
</div>
</Router>
The component is not been displayed when I navigate to localhost:3000/signup
Is it because react router is updated to v4 and they way you route in react has now changed?
I have my main.js file
import Signup from '../imports/ui/Signup';
import
const routes = (
<Router history={browserHistory}>
<Route path="/signup" component={Signup}/>
</Router>
);
Signup component
import React from 'react';
export default class Signup extends React.Component {
render() {
return <p>Signup</p>
}
}
I'm using react router v4, also using Meteor.
React Router v4 is a re-write of React Router so you'll have to read the new API and adjust your code accordingly. I suggest going through all the examples which can be found here. Here's the basic example that looks similar to your code. The biggest thing you'll notice is you no longer have a centralized route config. Instead, you render `` s dynamically when you need them.
import React from 'react'
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom'
const BasicExample = () => (
<Router>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/topics">Topics</Link></li>
</ul>
<hr/>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/topics" component={Topics}/>
</div>
</Router>
)
const Home = () => (
<div>
<h2>Home</h2>
</div>
)
const About = () => (
<div>
<h2>About</h2>
</div>
)
const Topics = ({ match }) => (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to={`${match.url}/rendering`}>
Rendering with React
</Link>
</li>
<li>
<Link to={`${match.url}/components`}>
Components
</Link>
</li>
<li>
<Link to={`${match.url}/props-v-state`}>
Props v. State
</Link>
</li>
</ul>
<Route path={`${match.url}/:topicId`} component={Topic}/>
<Route exact path={match.url} render={() => (
<h3>Please select a topic.</h3>
)}/>
</div>
)
const Topic = ({ match }) => (
<div>
<h3>{match.params.topicId}</h3>
</div>
)
export default BasicExample