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.
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.
import Sign from './sign.js'`
import Login from './login.js'
import {BrowserRouter, Link} from 'react-router-dom'
class App extends React.Component{
render(){
return(
<BrowserRouter>
<Link to="/login">Login</Link>
<Link to="/signup">Sign Up</Link>
<Route exact path="/login" >
<Login />
</Route>
<Route path="/signup">
<Signup />
</Route>
</BrowserRouter>
)}}
export default App;
So my problem is, Upon compiling this code, it only loads the children component. But can you help me to understand that how can I load whole page instead of loading these components into same page.
I tried these methods though.
1. Tried to make a new page which loads these two pages, such as login and sign up. But that leaves me with two links, which I do not want.
2. I tried changing the links using above method from each component, and loads the page in parent app. But it gave me error of computed match.
Please I am a new learner, help me out.
The earlier version of React had this bug, on updating the link. The previous version was not refreshing the page.
The code below will render a link that I can click on, and when I click on it, I can see the URL changing to have /japanese_game for the URL path. However... nothing appears to change on the page, the link that says "Japanese" is still there, unchanged. It should display the other stuff in <Route path="/japanese_game">, or rather, that's what I would like it to do.
What am I doing wrong?
import React from 'react';
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
import './App.css';
function App() {
return (
<div className="App container">
<Router>
<Switch>
<Route path="/">
<Link to="/japanese_game">
<div className="language-option">
Japanese
日本語
</div>
</Link>
</Route>
<Route path="/japanese_game">
<h1>Japanese Game</h1>
<Link to="/">
Go back
</Link>
</Route>
</Switch>
</Router>
</div>
);
}
export default App;
Change the order, it compares and selects on the basis of which matches first. put the Route with "/japanese_game" first.
The <Switch> component render the first route he match (doc).
When you go to /japanese_game, you also hit / route, so he render the component under the / route.
To prevent that, you have 2 options:
Add an exact props to your route / : <Route exact path="/"> (hightly recommanded)
Change the ordre of your route (not recommanded at all)
Change the order of the routes or alternatively use an "exact" flag.
<Route exact path="/japanese_game">
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 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="/">