so I'm trying to create routing for my react.js app by using react-router v.6.
I already tried to do changes for the v.6 but for some reason my app didn't show anything, can anyone help me ?
So Navigation.js file is for Routing, Header.js filled with button for changing route and App.js is used to display them.
App.js:
<div>
<Header/>
<Outlet/>
</div>
Header.js:
<>
<Link to="/">Home</Link>
<Link to="/Productlist">Product</Link>
<Link to="/Contact">Contact Us</Link>
</>
Navigation.js:
<>
<Routes>
<Route exact path="/" element={<Home/>}>
<Route exact path="ProductList" element={<Product/>}/>
<Route exact path="ContactUs" element={<Contact/>}/>
</Route>
</Routes>
</>
I don't know if this will solve your problem but first you can start by replacing your Navigation.js by :
<Routes>
<Route path="/" element={<Home/>} />
<Route path="ProductList" element={<Product/>}/>
<Route path="ContactUs" element={<Contact/>}/>
</Routes>
In this case you don't need nested routes.
Then, I don't think it's a good idea to use capitalize letter in path.
Related
I cannot comprehend how to use React Router properly. I want a component, rendered at the root ("/") to have multiple routes and redirect to "/projects" by default. Routes that I want to have are these:
"/projects"
"/projects/project/:projectId/"
"/projects/project/:projectId/device/:deviceId/"
"/projects/project/:projectId/device/:deviceId/task/:taskId/"
Anyway, whatever I try, I cannot render anything past the second route despite link href matching the route path.
In a sense, I do not really want to have nested routes (at least not in the way they are implemented here, just replace components according to path instead of appending.
Here is CodeSandbox link with one of many attempts.
Here are my routes:
<Switch>
<Redirect exact from="/" to="/projects/" />
<Route path="/projects/" exact>
<p>List of projects.</p>
<Link to="/projects/project/1/">Project #1</Link>
</Route>
<Route path="/projects/project/:projectId/">
<p>List of devices</p>
<Link to="/projects/project/1/device/1/">Device #1</Link>
</Route>
<Route path="/projects/project/:projectId/device/:deviceId/">
<p>List of tasks</p>
<Link to="/projects/project/1/device/1/task/1/">Task #1</Link>
</Route>
<Route path="/projects/project/:projectId/device/:deviceId/task/:taskId/">
<p>Task info.</p>
</Route>
</Switch>
This can be solved by adding exact to the other routes.
Updated working Codesandbox
The reason for this is /projects/project/:projectId/ is the first matching route, even for a list of tasks because of the wildcard :projectId.
<Route exact path="/projects/project/:projectId/">
<p> List of devices </p>
<Link to="/projects/project/1/device/1/"> Device #1 </Link>
</Route>
<Route exact path="/projects/project/:projectId/device/:deviceId/">
<p> List of tasks </p>
<Link to="/projects/project/1/device/1/task/1/"> Task #1 </Link>
</Route>
<Route exact path="/projects/project/:projectId/device/:deviceId/task/:taskId/">
<p> Task info. </p>
</Route>
The issue is that in the Switch component that path order and specificity matters! Keep in mind that the Switch "Renders the first child <Route> or <Redirect> that matches the location."
To resolve you should reorder the routes in inverse order of path specificity. In other words, you should try to match the more specific paths before the less specific paths. When done correctly it removes the need to sprinkle the exact prop all over the code.
The exact prop is not necessary in about 99.9% of use cases.
Example:
<Switch>
<Route path="/projects/project/:projectId/device/:deviceId/task/:taskId">
<p>Task info</p>
</Route>
<Route path="/projects/project/:projectId/device/:deviceId">
<p>List of tasks</p>
<Link to="/projects/project/1/device/1/task/1">Task #1</Link>
... other task links ...
</Route>
<Route path="/projects/project/:projectId">
<p>List of devices</p>
<Link to="/projects/project/1/device/1">Device #1</Link>
... other device links ...
</Route>
<Route path="/projects">
<p>List of projects</p>
<Link to="/projects/project/1">Project #1</Link>
... other project links ...
</Route>
{/* Anything not handled above redirects to "/projects" */}
<Redirect to="/projects" />
</Switch>
I am designing a users dashboard in React, wherein User logs in and navigate to his dashboard with other links such as Archived, Profile and Settings. My Login and then Navigating to HomePage is working fine.
I have designed the Dashboard, Archived, Profile and Settings Page Links in Sidebar. Now when I am navigating to the Links. It takes me to a new URL path and my Sidebar disappears. I want my sidebar to still appear on all pages as long as I am logged in.
Below is my App.js where I have designed the upper level route:
return (
<div>
<Router history={history}>
<Switch>
<PrivateRoute exact path="/" component={HomePage} />
<Route path="/login" component={LoginPage} />
<Route path="/register" component={RegisterPage} />
<Redirect from="*" to="/" />
</Switch>
</Router>
</div>
);
Once User is on HomePage, I need the dashboard and other links to show. and when User clicks on any Sidebar link, Sidebar should still be there while the other page opens. So I added the inner Routes to the HomePage.jsx like this:
return (
<div>
<Router history={history}>
<Sidebar />
<Switch>
<Route path="/" component={Dashboard} />
<Route path="/archived" component={ArchivedPage} />
<Route path="/profile" component={ProfilePage} />
<Route path="/settings" component={SettingsPage} />
{/* <Redirect from="*" to="/" /> */}
</Switch>
</Router>
</div>
);
But it doesn't work. Can anyone please help me understanding if this is correct. or how can I achieve the required result.
Please let me know if you need any other details.
Thank you.
Issue
The issue is that you are exactly matching "/" to render HomePage, but then as soon as the path is any deeper, like "/archived", it no longer exactly matches and HomePage is unmounted.
You should not render a Router within another Router, you need only one router per app to provide the routing context.
Solution
Remove the inner router (and any other nested routers!!). Remove the exact prop on the "/" path and reorder the routes to specify the more specific paths before less specific paths so the Switch can actually do its job and match and render the appropriate route.
App
Reorder the more specific "/login" and "/register" paths to be matched prior to the less specific "/" path. If you had, for example, a "/login/google" path, this is more specific than "/login" and would be ordered earlier.
return (
<div>
<Router history={history}>
<Switch>
<Route path="/login" component={LoginPage} />
<Route path="/register" component={RegisterPage} />
<PrivateRoute path="/" component={HomePage} />
<Redirect to="/" />
</Switch>
</Router>
</div>
);
HomePage
Move the Dashboard to the last route position so if no other route above it is matched and returned then the dashboard is matched and rendered.
return (
<div>
<Sidebar />
<Switch>
<Route path="/archived" component={ArchivedPage} />
<Route path="/profile" component={ProfilePage} />
<Route path="/settings" component={SettingsPage} />
<Route component={Dashboard} />
</Switch>
</div>
);
in first place your doing something wrong you cant put a Router inside a Router,
you haver a Router in app then inside a component that is inside of app you have another Router thats a problem i dont know if that solves your problem but try it just delete Router in homepage
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 have 2 level of route, the first layer it look like this
<BrowserRouter>
<div>
<AuthRoute></AuthRoute>
<Switch>
<Route path='/dashboard' component={Dashboard} />
</Switch>
</div>
</BrowserRouter>
where in AuthRoute I have a redirect upon componentDidMount
this.props.history.replace(/dashboard/redirected)
The problem is within the dashboard/index which is my 2nd level of route config
<BrowserRouter>
<Switch>
<Route exact path='/dashboard' component={()=><h1>dashboard index</h1>} />
<Route exact path='/dashboard/somewhere' component={()=><h1>somewhere</h1>} />
<Route exact path='/dashboard/redirected' component={() => <h1>redirected</h1>} />
</Switch>
</BrowserRouter>
The route changed to /dashboard/redirect but the component didn't render the correct one if you refresh on says /dashboard/somewhere or /dashboard/
You can see the problem clearer in the demo I setup https://codesandbox.io/s/v0v4qok38l
You only need one <BrowserRouter> in the application - removing it from dashboard/index.js will fix your issue.