I'm learning about react so I'm developing a personal blog with it. Moreover I use react-route but I've a problem because I don't understand why a route doesn't render (the route: /articule/:id). You can see the code in repository.
In the index.js define the route:
//it works
//index.js
const app = (
<Router>
<Switch>
<Route exact path="/" component={IRMBlog} />
<Route path="/articule/:id" component={IRMArticule}/>
</Switch>
</Router>
);
But If I move the line <Route path="/articule/:id" component={IRMArticule}/> to other file It doesn't work, why?
The file when I move the line of code is irm-articule-list.js
render() {
return (
<div className="column is-10 is-offset-1">
<IRMArticuleBox></IRMArticuleBox>
<IRMArticuleBox></IRMArticuleBox>
<Route path="/articule/:id" component={IRMArticule}/>
</div>
);
}
In the file irm-articule-box.js, I've <Link to="/articule/001">
Because application must have only one router, and router in react it's almost root component, one input for matching your urls
Like this.
import React, { Component } from 'react;
import { Link } from 'react-router-dom';
class articuleDetails extends Component {
render(){
return (
.....
<Link to="/articule/123"> articule name</Link>
...
)
}
}
Why do you want to move it?
In general you should know that Route must be inside a Router, and its job is to tell the browser which component to render when its path matches the location. It is not a hyperlink like the tag in HTML.
If your intention was hyperlink you should use <Link to="/">
Related
So basically, I have a problem with react router not rendering my SystemSidebar. I want to scroll through my SystemSidebar components, but my problem is when I press on 'LinkSoundIcon' it redirects me to 'a new page' but that page doesnt render my systemSidebar . I want when I press on any of the links of my sidebar that my sidebar remains
import React from 'react'
import './SystemSidebar.css'
import SoundIcon from '#material-ui/icons/Computer';
import ComputerIcon from '#material-ui/icons/Computer';
import { BrowserRouter, Route, Switch, Link } from 'react-router-dom';
import Sound from './Sound';
import Computer from './Computer;
const SystemSidebar=()=> {
return (
<div className='system'>
<div className="sidebar">
<Link to='Sound'><VolumeUpIcon /></Link>
<h4> Sound</h4>
<Link to='Computer'><ComputerIcon /></Link>
<h4> Computer</h4>
</div>
</div>
);
};
import React,{Component} from 'react'
import Sound from './Sound';
import Computer from './Computer';
import SystemSidebar from './SystemSidebar';
class MainSystem extends Component {
render(){
return (
<div className="MAIN">
<BrowserRouter>
<SystemSidebar />
<Switch>
<Route exact path="/" component={SystemSidebar} />
<Route exact path="/Sound" component={Sound}/>
<Route exact path="/Computer" component={Computer}/>
</Switch>
</BrowserRouter>
</div>
);
}
}
export default MainSystem;
<Link to='/Sound'><VolumeUpIcon /></Link>
answer of your first problem and second if you want to access sidebar in each component then don't put it in switch route , simply put it outside the routing... or if u want to access it with specific route then try using nested routing
Okay, so it seems a little wonky with your copy pasting (I hope this is just a problem that stems from copy and pasting and it's not like that in your code). But your Problem is here:
<Route exact path="/Sound" component={Sound}/>
You're saying here that the route should be EXACTLY http://<your root uri>/Sound
You should also use this exact route in the link if you want to hit it, this means you need to have the slash there:
<Link to='/Sound'><VolumeUpIcon /></Link>
Update:
So according to your comment you want the sidebar to stay when you click a link. In this case, take a look at your code:
<Switch>
<Route exact path="/" component={SystemSidebar} />
<Route exact path="/Sound" component={Sound}/>
<Route exact path="/Computer" component={Computer}/>
</Switch>
You define here that the component SystemSidebar will only be loaded when you're at the Root directory ("/") of your App. It will be unloaded when you change that directory, for example, to "/Sound". SystemSidebar will be unloaded and Sound will be loaded instead.
Since your Sidebar should always be shown, it needs to be in your Main App and outside of your actual Router logic. Remember what the React Router does: It switches out components depending on which directory (which Sub-URL) you're in. It's best practice to have a Sidebar, an App Bar or similar things that are always there to be their own components. Your actual content should live in a separate container, where the needed component can be swapped out by the Router if need be. So something like this:
class MainSystem extends Component {
render(){
return (
<div className="MAIN">
<SystemSidebar />
<div className="ContentContainer">
<BrowserRouter>
<Switch>
<Route exact path="/Sound" component={Sound}/>
<Route exact path="/Computer" component={Computer}/>
{/* Route "/" should be last because it acts as fallback! */}
<Route exact path="/" component={StartPage} />
</Switch>
</BrowserRouter>
</div>
</div>
);
}
}
That's pretty basic but I hope you get the gist of it.
Also, I'd encourage you to take a look at an UI framework like Material UI for example. It already provides components ready for use (like your Sidebar which is called Drawer there), it's mobile first and easy to use with responsive design.
probably a simple question for most but, why isn't my component rendering when my url updates, when I update the url manually it works but the links i'm using do not?
I have included my links component below, the display bar should display as a nav (so on every route) but the Newcase component should only display on its specified route. I have tried using the exact prop on it.
import React, { Component } from 'react'
import { BrowserRouter as Router, Route,Link } from 'react-router-dom';
export default class DisplayBar extends Component {
render() {
return (
<div>
<Router>
<Link to="/">home</Link>
<Link to="/form">form</Link>
</Router>
</div>
)
}
}
and here is my router in my main app.js
render(){
return (
<Router>
<Route path = '/' component ={DisplayBar} />
<switch>
<Route exact path='/form' component = {NewCase} />
</switch>
</Router>
);
}
You don't need to wrap your links with Router, Remove Router
<Link to="/">home</Link>
<Link to="/form">form</Link>
and also put <Route path = '/' component ={DisplayBar} /> inside switch
<switch>
<Route path = '/' component ={DisplayBar} />
<Route exact path='/form' component = {UserAdd} />
</switch>
I'm working on an user-list project made with React/ React Router for a community I'm part of and I've been running into a problem I can not find the root of.
I have a nested Router set up, to have a userlist appear on the click of a button (url/player) and then - in the userlist - have the profile of that user appear on a click on the name (url/player/:id). This works fine so far!
BUT:
When I'm on a user profile (url/player/:id) and click the link to get back to the userlist, it does not render the userlist-component - though the url in the browser itself changes back to (url/player).
I can't figure out how to make the general userlist reappear again and would surely appreciate some input.
Since the project has multiple components, I separated them into different files, where my problem my lay.
I still tried to reconstruct the instructions of different tutorials for nested Routes. Maybe I'm just overlooking something basic, but I cant seem to find it.
Main Navigation Router in the index.js
<Router>
<Navigation />
<div className="contentBox">
<Route path="/" exact component={Home} />
<Route path="/player" exact component={Playerlist} />
</div>
</Router>;
Userlist Router in the Playerlist-Component
<Router>
<Route path="/player" exact component={Playerlist} />
<Route path="/player/:id" component={Playerprofile} />
</Router>;
The weird thing is, only the Playerlist-Link does not work anylonger. If I click on either the "Home"-Link or any other Navigation, it works. So I assume it has something to do with the rerendering.
I'm sorry if this question seems obvious, I'm still a beginner and appreciate any help! Thank you!
You should improve the nested routing of your app:
No need to wrap PlayerList component with Router. Use Router only in root component.
Don't use Route to PlayerList component within the component itself.
Do use Route to PlayerList component in index.js, but without exact (so routing to '/player/:id' routes work).
Here are snippets of updated code:
App.js (in your case index.js):
export default function App() {
return (
<Router>
<Navigation />
<Route path="/" exact component={ Home } />
<Route path="/player" component={ PlayerList } />
</Router>
);
}
PlayerList.js
export default function PlayerList({ match }) {
return (
<div>
<h1>Player List</h1>
<Route path={`${match.path}/:id`} component={ PlayerProfile } />
</div>
);
}
PlayerProfile.js
export default function PlayerProfile({ match }) {
return <div>Player Profile { match.params.id }</div>;
}
Navigation.js (draft):
export default function Navigation() {
return <nav>
<Link to="/">Home</Link>
<Link to="/player">PlayerList</Link>
<Link to="/player/1">Player 1</Link>
<Link to="/player/2">Player 2</Link>
<Link to="/player/3">Player 3</Link>
</nav>;
}
Though I'd recommend to move the Links to "/player/:id" into PlayerList component.
You can find official notes on nested routing here. Hope that helps.
i'm trying to use react router in my reactjs app. And I encountered this problem:
This is what i'm trying to do:
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import About from '../Pages/About';
import Home from '../Pages/Home';
import Topics from '../Pages/Topics';
import LinkTest from '../Pages/LinkTest';
class AppRouter extends Component {
render() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/home">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/topics">Topics</Link>
</li>
<Route path="/home" component={LinkTest}/>
</ul>
<hr />
<Route path="/home" component={Home}/>
<Route path="/about" component={About} />
<Route path="/topics" component={Topics} />
</div>
</Router>
);
}
}
export default AppRouter;
Ignore "about" and "topic" component, when I click on "Home" link, it should target 2 routes, one will render "LinkTest" and the other renders "Home".
This is what inside "LinkTest":
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
class LinkTest extends Component {
render() {
const {match}=this.props;
return (
<div>
<Link to={`${match.url}/Test`}>Link To Test</Link>
</div>
);
}
}
export default LinkTest;
And inside my "Home" component:
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Test from './Test';
class Home extends Component {
render() {
const {match} = this.props;
console.log(match.url);
return (
<Router>
<div>
<h2>
Hello from Home page
<Link to={`${match.url}/Test`}>Link To Test</Link>
<Route path={`${match.url}/Test`} component={Test}/>
</h2>
</div>
</Router>
);
}
}
export default Home;
However:
When i click on the link inside "LinkTest" component (which was rendered earlier), the url on the browser is shown "http://localhost:3000/home/Test", but nothing happens.
When i clicked on the link inside "Home" component, (which was rendered the same time as the "LinkTest" using the same link), it showed the same url on the browser: "http://localhost:3000/home/Test", only this time it rendered the "Test" component.
Why does this happen? (what i want to achieve is I want to use the link inside "LinkTest" to render "Test" component inside "Home" component, or something similar).
I hope this is clear enough.
You can do it in following way:
<Route exact path='/a' component={A} />
<Route path='/b' component={B} />
// Following should be router inside Component B
<Route exact path='/b/abc' component={OtherComponent}
If you want I've prepared few react-router 4 examples. These are hosted here. https://github.com/SandipNirmal/react-router-examples
If you need Nested routing inside ComponentB you should add Links for those Routes as well. And use match.url and match.path to build the nested Links and Routes.
const ComponentB = ({ match }) => {
return (
<div>
<div>
<ul>
<li><Link to={`${match.url}/c`}>Component C</Link></li>
// more Links
<li><Link to={`${match.url}/css`}>CSS</Link></li>
<li><Link to={`${match.url}/react`}>React</Link></li>
</ul>
</div>
<div>
<Route path={`${match.path}/c`} component={ComponentC} />
// more nested Routes
<Route path={`${match.path}/css`} render={() => { return <h1>CSS</h1> }}/>
<Route path={`${match.path}/react`} render={() => { return <h1>React</h1> }}/>
</div>
</div>
);
}
Nested routing
Components created via Route will automatically be passed the following prop objects: match, location and history.
Using match you can implement nested Routes. The match object contains the following properties:
params — (object) Key/value pairs parsed from the URL corresponding
to the dynamic segments of the path
isExact — (boolean) true if the entire URL was matched (no trailing characters)
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
Reference
https://medium.freecodecamp.org/beginners-guide-to-react-router-4-8959ceb3ad58
https://medium.com/#pshrmn/a-simple-react-router-v4-tutorial-7f23ff27adf
I'm trying to embrace the react-router 4 philosophy of having routing spread throughout the app instead of one central place. For brevity, <App> effectively spits out the following in its render():
<BrowserRouter>
<Link to='/' />
<Link to='/linkb' />
<Switch>
<Route exact path='/' component={ComponentA}>
<Route exact path='/linkb' component={ComponentB>
</Switch>
</BrowserRouter>
...
So far so good: the nav links help me to route to the corresponding components A and B and my 2 page app works fine.
The problem I'm having is that, inside componentB, now I want it to have its own child routes. Though these routes will be 'grandchildren' of <App/>, I see no reason why <App/> should know or care about them. I built this (surrounding content and css stuff mostly ripped out for clarity):
Component B
import React, { Component } from "react";
import { BrowserRouter, Switch, Route, Link } from 'react-router-dom';
import ComponentC from './ComponentC';
import ComponentD from './ComponentD';
export default class ComponentB extends Component {
constructor(props) { super(props);}
render() {
return (
<div>
<div>
<Link to='/linkb/c' className='btn'>link C</Link>
<Link to='/linkb/d' className='btn'>link D</Link>
</div>
{this.props.children}
<Switch>
<Route exact path="linkb/c" component={ComponentC}/>
<Route exact path="linkb/d" component={ComponentD}/>
</Switch>
</div>
);
}
}
When I click link C or link D, the url updates in the browser bar but nothing changes on the page / the new component is not rendered. What am I doing wrong?
OK - so the only way I've gotten this to work is to stop hardcoding the paths in my child components, and use the path segments passed in via react-router. Since these evaluate to the same thing (I think) I'm unsure why this fixes my problem, but it does:
<Link to={`${this.props.match.path}/c`}>link c </Link>
<Link to={`${this.props.match.path}/d`}>link d </Link>
And that works!! No idea why! If someone can explain why I'll accept their answer instead of mine.
update: appears to have been a case of absolute vs relative urls. Using props.match.path avoid that kind of confusion.