<Link> in React doesn't forward to a new page - reactjs

Consider the code :
import React from 'react';
import { Link, BrowserRouter } from 'react-router-dom';
import { ReactComponent as Logo } from '../../assets/crown.svg';
import './header.styles.scss';
const Header = () => (
<BrowserRouter>
<div className='header'>
<Link className='logo-container' to='/'>
<Logo className='logo' />
</Link>
<div className='options'>
<Link className='option' to='/shop'>
SHOP
</Link>
<Link className='option' to='/contact'>
CONTACT
</Link>
</div>
</div>
</BrowserRouter>
);
export default Header;
This is a header that I use in my App.
Look like this :
When I click on the crown the URL (in the browser) changes , but the page doesn't change , it stays on the same page.
Same thing happens with the other Links , CONTACT & SHOP.
What's wrong with the <Link> tag ? Why doesn't it forward to the to that's written on the Link tag ?

Did you setup the routes? This would be in AppRouter.js for example:
<BrowserRouter>
<div>
<Header />
<Switch>
<Route path='/' component={Home} exact={true} />
<Route path='/shop' component={Shop} exact={true }/>
<Route path='/contact' component={Contact} exact={true} />
<Route component={ErrorPage} />
</Switch>
</div>
</BrowserRouter>

If you want navigate your user try use NavLink
or add withRouter to component and push them to the other pages
-- NavLink solution :
import { NavLink, BrowserRouter } from 'react-router-dom';
and then in your JSX use this instead
<NavLink className='logo-container' to='/'>
<Logo className='logo' />
</NavLink>
-- push solution:
import { withRouter , BrowserRouter } from 'react-router-dom';
export your component like this
export default withRouter(Header);
then you can use any tags you want and listen at events on them
<p className='logo-container' onClick = {() => props.history.push('/')}>
<Logo className='logo' />
</p>

in order to navigate to different components you have to define routers. So react-router-dom will know what to display.
The other thing is u cannot put BrowserRouter inside the Header component. Component BrowserRouter wraps the history object in the browser and passes it to down to component tree. BrowserRouter is a wrapper. Header should be placed inside the BrowserRouter but not here. just create your Header Component without BrowserRouter.
here is how you should properly implement routing in react.js
in src/omponents folder create your components for routes.
src/component/shop.js:
import React from "react";
const Shop = () => <div>my shop component</div>; //define your component
export default Shop;
create all other components like so including Header but without BrowserRouter. then in src folder create a new directory name routers. inside of it create AppRouter.js
src/routers/AppRouter.js
import { BrowserRouter, Route, Switch } from "react-router-dom";
import React from "react";
import Shop from "../components/Shop";
//import all other routes from components directory.
import Header from "../components/Header"
const AppRouter = () => (
<BrowserRouter>
<div>
<Header />
<Switch>
<Route path="/" component={YourHomeComponent} exact={true} />
<Route path="/contact" component={Contact} />
<Route path="/shop" component={Shop} />
<Route component={NotFound} />
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;
// When react-router sees “Switch” it is going to move through your route definitions in order and it’s going to stop when it finds a match.
finally in app.js
import React from "react";
import ReactDOM from "react-dom";
import AppRouter from "./routers/AppRouter";
ReactDOM.render(<AppRouter />, document.getElementById("app"));

Related

When i change tag "a" to NavLink i dont see my page. In devtools appear many errors? [duplicate]

This question already has answers here:
Error: useHref() may be used only in the context of a <Router> component. It works when I directly put the url as localhost:3000/experiences
(11 answers)
Closed 3 months ago.
I try to make site with router, but using anchor tag <a> reloads the page. When I changed them to NavLink component my site broke. I see white page and many errors in devtools.
App.js
import "./App.css";
import "./Components/MainContent/Main/MainContent.module.css"
import "./Components/Header/Header.module.css"
import "./Components/Navbar/Navbar.module.css"
import Header from "./Components/Header/Header";
import Navbar from "./Components/Navbar/Navbar";
import MainContent from "./Components/MainContent/Main/MainContent";
import { Router, Route, Routes, BrowserRouter } from "react-router-dom";
import Catalog from "./Components/MainContent/Catalog/Catalog"
import Busket from "./Components/MainContent/Busket/Busket"
import Contacts from "./Components/MainContent/Contacts/Contacts"
function App() {
return (
<div className="appWeb">
<Header />
<Navbar />
<BrowserRouter>
<Routes>
<Route path='/' element={<MainContent />} />
<Route path='/index.html' element={<MainContent />} />
<Route path='/Catalog' element={<Catalog />} />
<Route path='/Busket' element={<Busket />} />
<Route path='/Contacts' element={<Contacts />} />
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
Navbar.js
import React from "react";
import styles from "./Navbar.module.css"
import { NavLink } from "react-router-dom";
function Navbar() {
return (
<nav className={styles.navbar}>
<div className={styles.navbar__links}>
<NavLink to="/">Главная</NavLink>
</div>
<div className={styles.navbar__links}>
<NavLink to="Catalog">Каталог</NavLink>
</div>
<div className={styles.navbar__links}>
<NavLink to="/Busket">Корзина</NavLink>
</div>
<div className={styles.navbar__links}>
<NavLink to="/Contacts">Контакты</NavLink>
</div>
</nav>
);
}
export default Navbar;
To be working, NavLinks should be nested inside a Router component. So your Navbar containing the links should move from outside the router:
<Navbar/>
<BrowserRouter>
<Routes>
...
To inside the router:
<BrowserRouter>
<Navbar/>
<Routes>
...

Why do my Link To links not work in React-Router?

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.

This is a question about setting up routing routes

import React from 'react';
import {Link, Route, BrowserRouter as Router, Switch} from "react-router-dom";
import './App.css';
import User from './Component/User';
import AdContent from './Component/AdContent';
//Home.js
function Home(){
return(
<Router>
<header>
<div>ShareAdsLink</div>
<nav>
<Link to="/User">
<li className="button">LogIn</li>
</Link>
<Link to="/AdContent">
<li className="button">SignUp</li>
</Link>
</nav>
</header>
<Switch>
<Route path="/User" component={User} />
<Route path="/Adcontent" component={AdContent}/>
</Switch>
</Router>
);
}export default Home;
//App.js
import React from 'react';
import Home from './Home';
import {Route, BrowserRouter as Router, Switch} from "react-router-dom";
function App() {
return (
<Router>
<Route path="/" component={Home} exact/>
</Router>
);
}
export default App;
What I'm trying to do is to show the default screen (the page you see as soon as you enter) in Home.
There are login and signup buttons in Home, and if i click this button, a new page should appear. But in my results, a new page should be opened, separate from the contents of Home, but the contents of Home will be displayed too.
How can I display a new page? Using exact keywords is useless.
That is my first question.
Secondly, can you give me advice on where(ex, App.js ,,) to configure the base screen?
Restructuring your app like this should help:
//App.js
import React from "react";
import Home from "./Home";
import { Route, BrowserRouter as Router, Switch } from "react-router-dom";
import User from "./Component/User";
import AdContent from "./Component/AdContent";
function App() {
return (
<Router>
<Route path="/" exact component={Home} />
<Switch>
<Route exact path="/User" component={User} />
<Route path="/Adcontent" component={AdContent} />
</Switch>
</Router>
);
}
export default App;
//Home.jsx
import React from "react";
import { Link } from "react-router-dom";
function Home() {
return (
<header>
<div>ShareAdsLink</div>
<nav>
<Link to="/User">
<li className="button">LogIn</li>
</Link>
<Link to="/AdContent">
<li className="button">SignUp</li>
</Link>
</nav>
</header>
);
}
export default Home;
Issue
You are rendering your homepage header no matter what, regardless of path/page.
Solution
Just render the header content into its own route within the Switch, and move the routes into App. By placing the less specific home path ("/") last/later then more specific paths will be attempted to be matched first, and if no prior path is matched then the header will render.
function App() {
return (
<Router>
<Switch>
<Route path="/User" component={User} />
<Route path="/Adcontent" component={AdContent} />
<Route path="/">
<header>
<div>ShareAdsLink</div>
<nav>
<Link to="/User">
<li className="button">LogIn</li>
</Link>
<Link to="/AdContent">
<li className="button">SignUp</li>
</Link>
</nav>
</header>
</Route>
</Switch>
</Router>
);
}

React Router Deep Link with dynamic

I want deep link with dynamic route
My code is this
import React from 'react';
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import Home from '../Routes/Home';
import Add from '../Routes/Add';
import Region from '../Routes/Region';
import Stores from '../Routes/Region/Stores';
function App() {
return (
<div className="App">
<Router>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/addBook" component={Add} />
<Route path="/:region" component={Region} />
<Route path="/:region/:store" component={Stores} />
</Switch>
<Link to={`/${"ulsan"}`}>
<button>go</button>
</Link>
</Router>
</div>
);
}
export default App;
and my region page is this
import React from 'react';
import { Link } from 'react-router-dom';
function Region() {
const store = "hello"
return(
<>
<Link to={`/${"ulsan"}/${store}`}>
<button>store</button>
</Link>
<div>Region</div>
</>
)
}
export default Region;
when I click store button, page is staying Region
I don't know how to move Stoer page with dynamic route
what is the problem???
Sorry I'm not good at English
The Problem is how you declare your routes, you need to add exact attributs:
<Route exact path="/:region" component={Region} />

React not rendering Route Components

I am building a consumer facing app with a admin dashboard. I want to keep the routing separate for them and so trying to delegate :-
App.js
import React, {Component} from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
//styles
import './style/bootstrap/bootstrap.scss';
//apps
import Mainapp from './mainapp/Mainapp';
import Admin from './admin/Admin';
const MainappContainer = () => (
<Mainapp />
);
const AdminContainer = () => (
<Admin />
);
class App extends Component{
render(){
return (
<Router>
<Switch>
<Route path="/admin" component={AdminContainer}/>
<Route path="/" component={MainappContainer}/>
</Switch>
</Router>
)
}
}
export default App;
Admin.js
import React, {Component} from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
//styles
import './admin-style.scss';
//layout
import ControlPanel from './component/layout/ControlPanel';
import Navbar from './component/layout/Navbar';
//pages
import Quote from './component/pages/quote/Quote';
class Admin extends Component{
render(){
return (
<div className="adminWrapper">
<ControlPanel />
<section className="viewPanel">
<Navbar />
<Router>
<Route path="/quote" component={Quote}/>
</Router>
</section>
</div>
)
}
}
export default Admin;
However when I hit the URL
http://localhost:3000/admin/quote
it doesn't seem to load the quote component
Quote.js
import React, { Component } from 'react';
class Quote extends Component {
render() {
return (
<div className="float-right pr-3">
<h3>
Quote Page
</h3>
</div>
)
}
}
export default Quote;
When dealing with nested subroutes, the easiest solution is to use match.
path - (string) The path pattern used to match. Useful for building nested
Routes.
url - (string) The matched portion of the URL. Useful for building
nested Links.
By design, components placed inside a Route's component render method are given several additional props from react-router-dom. Among them are history and match. You can leverage these props to either to match against sub routes and/or to control browser history location.
In addition, you only need one instance of BrowserRouter sitting at the top-level of the application, then you can use Switch to optionally render any main or sub routes. And you don't need to use class components unless you're utilizing state and/or a class field.
A very basic, rudimentary working example of your application:
src/components/Admin/index.js
import React from "react";
import { Switch, Link, Route } from "react-router-dom";
import ControlPanel from "../ControlPanel";
import Quote from "../Quote";
// since Admin is placed inside a Route's component render
// method, it has access to history and match
function Admin({ history, match }) {
return (
<div className="adminWrapper">
<ControlPanel />
<section className="viewPanel">
<Link to={`${match.url}/quote`}>View quote</Link>
<br />
<Switch>
<Route exact path={`${match.path}/quote`} component={Quote} />
</Switch>
</section>
<br />
<button type="button" onClick={() => history.goBack()}>
Go Back
</button>
</div>
);
}
export default Admin;
index.js
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Link, Route, Switch } from "react-router-dom";
import Admin from "./components/Admin";
const linkStyle = {
padding: "0 10px"
};
function App() {
return (
<BrowserRouter>
<Link style={linkStyle} to="/">
Home
</Link>
<Link style={linkStyle} to="/admin">
Admin
</Link>
<Switch>
<Route path="/admin" component={Admin} />
<Route path="/" render={() => <h1>Main App</h1>} />
</Switch>
</BrowserRouter>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
Follow the Nested Routing Example
The main changes you need to do are:
1. Remove the <Router></Router> from Admin component and
2. Prepend match.path to "/quotes", like it is done in Topics component in the example. In the example, Topics is a function component so it is receiving match as function parameter. As your Admin component is class component, you can access it as this.props.match in render method.
<Route path={`${this.props.match.path}/quote`} component={Quote}/>
<Route exact path="/admin" component={AdminContainer}/>
<Route exact path="/admin/quote" component={Quote}/>
This won't route you to /admin/quote instead it will route you to /admin/admin/quote.
Since it is inside admin just /quote is enough
<Route path="/admin" component={AdminContainer}/>
<Route path="/quote" component={Quote}/>

Resources