I am trying to use router in my app
so I used react-router-dom, but I am facing issues,
researched and found this link but still not helping me.
Invariant failed: You should not use <Route> outside a <Router>
can you tell me how to use route and link
i need to redirect to another page.
providing my code snippet and sandbox below.
https://codesandbox.io/s/still-smoke-uf731
let Channel = ({ channelName, channelString, onClick, active }) => (
<div onClick={onClick} className=" col-lg-2 col-md-4 col-sm-6 ">
<div>router</div>
<Router>
<Link to={"/here"}> here</Link>
<Switch>
<Route path="/auth" />
<Route path="/" />
</Switch>
</Router>
<div
className="channel-button"
style={{
backgroundColor: active === channelString ? "orange" : ""
}}
>
<p>{channelName}</p>
</div>
</div>
);
Use exact as an attribute in your home route like the following code.
<Router>
<Link to={"/here"}> here</Link>
<Switch>
<Route exact path="/" />
<Route path="/auth" />
</Switch>
</Router>
I checked your sandbox. Looks like a good start, but you messed some things up.
Here is my fork of your sandbox: https://codesandbox.io/embed/staging-fast-rr5k9
First, don't put react components in the containers, put them in the components folder and import them.
What was going on was, that you had brand new <Router> for every page you had. So I pulled the Router out. Its also not imported correctly. It should be
import { BrowserRouter as Router } from "react-router-dom";
So you pretty much need something like this
<div>
<Link to={"/bbc-news"}>BBC</Link>
</div>
<div>
<Link to={"/cnbc"}>CNBC</Link>
</div>
<Switch>
<Route
key={"fbbc-news"}
path="/bbc-news"
render={p => <Channel channelName="BBC" channelString="bbc-news" />}
/>
<Route
key={"cnbc"}
path="/cnbc"
render={p => <Channel channelName="CNBC" channelString="cnbc" />}
/>
</Switch>
</Router>
Where Channel component renders whats inside the channel. the key in Route is important, because it makes React properly trigger componentDidMount, which calls the thunk action which fetches (that one is perfect).
Then to access the results from fetch, which you have placed in Redux =>
const mapStateToProps = state => ({ json: state.json });
You don't need a lot of the things you had, so I have removed them, like the onClick, which was trying to do react routers job
You can try this:
import Stats from './containers/stats';
<Route
exact={true}
path="/"
component={Stats}
key="Mykey"
/>
Related
I am using the react router to create multiple webpages without changing my navbar and all it gives me is a blank page. I have tried multiple things such as a browser router, and switch and neither of them work.
function App() {
return (
<div className="App">
<Navbar />
<Router>
<Link to="/">Home</Link>
<Link to="/aggrid">Aggrid</Link>
<Route path="/" component={GhibliModal} />
<Route path="/aggrid" component={Aggrid} />
</Router>
</div>
);
}```
Well first things first, you need to wrap your whole App component with <BrowserRouter>, but I from what you said in the question, I would assume you already know that.
Secondly, you don't need the <Router> component. Read here.
From reading the documentation, all <Route> components must be wrapped in a <Routes> (note the 's' at the end) component.
And lastly, I'm pretty sure you cannot have <Link> components inside the <Routes> component.
Also, the component prop is now called element, so
<Route path="/" component={GhibliModal} />
should become
<Route path="/" element={<GhibliModal/>} />
You need to add <Outlet /> tag in the components that are loaded by Router.
I usually put it at the end of the JSX:
return (
<div>
<yourcodehere/>
<Outlet/>
</div>
)
I have my app like that
<Router>
<div className="App">
<Link to="/" style={{ textDecoration: "none" }}>
<header>Project Issues</header>
</Link>
<Switch>
<Route exact path="/">
<Issues />
</Route>
</Switch>
</div>
</Router>
Inside Issues component, I choose to render one of two components based on a window width condition, one of the two components is called TwoPagesLayout, in this component when the user clicks on some text, it should go to another component called IssueDetails.
Here's the part of the TwoPagesLayout component:
{issues.map((issue: any) => (
<div>
<Link to="/Details" style={{ textDecoration: "none" }}>
<p className="issue-title">{issue.title}</p>
</Link>
<hr></hr>
<Switch>
<Route exact path="/Details">
<IssueDetails issue={issue} />
</Route>
</Switch>
</div>
))}
The problem is when I click on the text, it goes to that url "http://localhost:3000/Details" but it appears as a blank white page, it doesn't render what is inside the page.
Hope I have made it clear, I am new to react so I think the question maybe sounds common.
<Route exact path="/">
<Issues />
</Route>
Since you've marked this as exact, once the url changes to /Details, it no longer matches, and so Issues unmounts. Since Issues unmounts, so too does its descendant IssueDetails. You probably want to do:
<Route path="/">
<Issues />
</Route>
The Issues component will only render on the "/" path. When the page is showing "/Details" the Issues component will not render, and that includes the nested Router.
For this reason (they’re confusing), I personally try to avoid nested routers, so I would suggest keeping all the Route components together unless you have a reason otherwise!
I'm in the process of trying to figure out how React Router Dom works, and have run into a problem that I am not even sure how to figure out.
If, within App.js, I have this snippet, then everything renders and navigates between the sections, just fine.
<Switch>
<Route path='/login-user' component={UserLoginForm} />
<Route path='/login-database' component={LoginDatabaseSelect} />
<Route path='/login-project' component={LoginProjectSelect} />
<Redirect path='/' exact to='/login-user' />
</Switch>
However, that is not the proper way, and I am trying to instead do this:
Create a different component that is referenced for this.
<Switch>
<Route path='/login' component={LoginSequence} />
<Redirect path='/' exact to='/login' />
</Switch>
And in LoginSequence the code is:
import React from 'react';
import { Route, Redirect, Switch } from 'react-router-dom';
import UserLoginForm from "./LoginSequence/loginUserPass";
import LoginDatabaseSelect from "./LoginSequence/loginDatabaseSelect";
import LoginProjectSelect from "./LoginSequence/loginProjectSelect";
class LoginSequence extends React.Component {
render () {
console.log('Login Sequence')
return (
<div>
<h1>Login Sequence</h1>
<Route path='/login-user' component={UserLoginForm} />
<Route path='/login-database' component={LoginDatabaseSelect} />
<Route path='/login-project' component={LoginProjectSelect} />
<Redirect path='/login' exact to='/login-database' />
</div>
)
}
}
export default LoginSequence;
however, this component, does not even seem to be called as the console.log does not output anything to console. Meaning that nothing is rendering, and it is not getting called.
Can someone point me in the right direction as to why this isn't working?
Edit: I fixed up the From and changed it to Path in the snippet of code where LoginSequence is called, since it had no effect, but path seems to be the normal way of doing it.
Change from to path in Redirect.
<Switch>
<Route path='/login' component={LoginSequence} />
<Redirect path='/' exact to='/login' />
</Switch>
Don't use Redirect use Route and call in the component you want to render
<Switch>
<Route path='/login-user' component={UserLoginForm} />
<Route path='/login-database' component={LoginDatabaseSelect} />
<Route path='/login-project' component={LoginProjectSelect} />
<Route path='/' exact component={login-user} />
</Switch>
After talking to a couple of people, and seeing a few more examples, something became a bit more clear that solved the issue.
Within App.js:
<Switch>
<Route path='/login' component={LoginSequence} />
<Redirect path='/' exact to='/login' />
</Switch>
And the LoginSequence component within LoginScreen.js:
class LoginSequence extends React.Component {
render () {
console.log('Login Sequence')
return (
<div>
<h1>Login Sequence</h1>
<Route path='/login/user' component={UserLoginForm} />
<Route path='/login/database' component={LoginDatabaseSelect} />
<Route path='/login/project' component={LoginProjectSelect} />
<Redirect path='/login' exact to='/login/user' />
</div>
)
}
}
What I noticed, is that the 'root' for referencing changes every time, so, once I redirect to /login to be loginsequence, the new area that components are looked for is within /login. Thus /login/<user/database/project> has to be the new path, rather than just /<user/database/project>, as it seems to look for the references of that, within App.js and can't find them, thus not rendering. Seems like RRD follows a 'tree' structure of a sort, and every time you want to nest it, you have to follow the structure of
/<path of component containing further routes>/<route of component referenced in component>
When I try to have nested routes on my root route I run into a problem.
I have 3 "main" routes:
<Switch>
<Route path="/" component={Home} />
<Route path="/login" component={Login} />
<Route path="/logout" component={Logout} />
</Switch>
On my Home component I have a nested router like this:
<div>
<Route path="/" render={() => <div>Home</div>} />
<Route path="/test" render={() => <div>Test Route</div>} />
</div>
The Home component has a sidebar HOC which contains the Links.
<Sidebar>
<Link to="/">Home</Link>
<Link to="/test">Test</Link>
<Link to="/logout">Logout</Link>
</Sidebar>
When Im on my Root component and click the Test link, the route on the nested router changes to the Test component which is correct. Whenever I go the login and/or logout route it tries to display that in the nested router in the Home component
Any idea what is going wrong?
EDIT: I've tried the example #Tholle provided. Unfortunately it still doesn't work the way I want to. See this CodeSandBox I made to reproduce my problem.
your links need to point to "/home/testX" and the nested routes need to handle "/home/testX". Also you will need a route for "/home" in the root. I don't believe the Link component is scoped to the route in which it is called. Meaning that to link to "/test1" assumes that is the base route. However, the rendering of test1 actually takes place in the home component.
To put it another way: In order to get to /home/test1 you must first get the home component (/home) to render which can then render the route for test1 (/home/test1)
Here's the codesandbox
Here is an example that provides a bit more flexibility codesandbox. This one will require a redirect of "/" because it depends on the path being used and it needs to be "/home" not "/".
Hope this helps. Hope I got it all right.
The Switch component makes sure that only the first Route that matches is rendered. To stop <Route path="/" component={Home} /> from always being rendered, you can set the exact prop to true.
Example (CodeSandbox)
<Switch>
<Route exact path="/" component={Home} />
<Route path="/login" component={Login} />
<Route path="/logout" component={Logout} />
</Switch>
I am creating an application using ReactJS. I am using react router v4 from react-router-dom.
I have written routes in index.js file.
<BrowserRouter>
<Switch>
<Route exact path="/" component={Login} />
<Route exact path='/dashboard' component={Viewport} />
</Switch>
</BrowserRouter>
Rest of the application in Viewport.js file.
return (
<div className="">
<Sidebar navigation={this.viewport} />
<HeaderBanner user={this.props.user} />
<div className="center-panel">
//todo
//Can I use router here?
</div>
</div>
)
After user login's, I am rendering Viewport which contains Sidebar and header bar by default. Based on the item click in the sidebar navigation, I need to render components dynamically. As of now, if I write anything in the place of todo, it renders only that component for the complete browser window.
Is there any way to use routers in multiple places of the application? If yes, how can I implement it? If no, what's the best solution?
As far as I have seen, routers will be stacked at one place in the application.
Thanks in advance.
I followed a tutorial on youtube recently which was very useful
So I took some of it and applied it to your setup
<BrowserRouter>
<div>
<Route exact path="/" component={Login} />
<Route exact path='/dashboard' component={Viewport} />
</div>
</BrowserRouter>
import { NavLink, Route } from 'react-router-dom';
class Viewport extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<div className="Side-bar">
<NavLink
activeClassName="active"
to={`${this.props.match.url}/sub-page-name-1`}>Sub Page 1</NavLink>
<NavLink
activeClassName="active"
to={`${this.props.match.url}/sub-page-name-2`}>Sub Page 2</NavLink>
<NavLink
activeClassName="active"
to={`${this.props.match.url}/sub-page-name-3`}>Sub Page 3</NavLink>
</div>
<HeaderBanner user={this.props.user} />
<div className="center-panel">
<Route path={`${this.props.match.url}/sub-page-name-1`} component={SubPagePanel1} />
<Route path={`${this.props.match.url}/sub-page-name-2`} component={SubPagePanel2} />
<Route path={`${this.props.match.url}/sub-page-name-3`} component={SubPagePanel3} />
</div>
</div>
)
}
}
I removed Switch as well because I didn't use it for my sub pages... :-S
Update: Have created a repo showing a working example of sub page content
https://github.com/PocketNinjaDesign/so-sub-routes-answer
Yes you can use <Routes> in as many places as you want. <Router> components are the ones you can only use once.