How to use react-router to navigate component with multiple pages - javascript

Suppose that I have 2 pages and several components. The first page is the login page and the other page is the main menu. The login page only has 1 component. Once the user has logged into the website I want react-router to navigate to the main menu, the main menu has navbar and some components right down below. I want it to be able to navigate to each component and keep the navbar at the top all the time even the URL has been changed.
Here the code I've tried
// Inside the root component
<BrowserRouter>
<Route path="/menu" component={MenuForm}/>
<Route path="/login" component={LoginForm}/>
</BrowserRouter>
//Inside the menu page component
<Navbar/>
<Route path="/shop" component={Shop}/>
<Route path="/categories" component={Categories}/>
With this code, I can only navigate to menu page and login page, but I can not navigate to Shop and categories which are the child component of main menu

You need to have home page
<Route path="/home" component={Home}/> // all your menu and everything here
now if from home you want to go to menu
you can do like this
<Route path="/home/menu" component={Menu}/>
This component will render in home page where you set nested routes so matching route component will render
<Route path="/home/menu" component={menu}/>
<Route path="/home/profile" component={Profile}/>

I suppose you should consider creating container components. Where the first container will be containing your login routes namely "Auth Container", and the another components should be into the App routes namely "App Container". And you can have your own wrapper.
const AppRoutes = () => {
return (
<>
<Navigation scrolling={scrolling} />
<Switch>
<ProtectedRoute exact path="/profile" component={UserProfile} />
<ProtectedRoute exact path="/my-orders" component={MyOrders} />
<ProtectedRoute path="/my-saved-result" component={SavedResults} />
</Switch>
</>
)
}

If you are using react-router v4, you could you Switch component to declaratively define your routes like below:
import { Switch, Route, Redirect } from 'react-router-dom';
const MenuForm = () => (
<div className="app-routes">
<NavBar />
<Switch>
<Route exact path="/menu">
<Redirect to="/menu/shop" />
</Route>
<Route path="/menu/shop" component={Shop} />
<Route path="/menu/categories" component={Categories} />
</Switch>
</div>
);

I'm using like this
<div className="main-panel">
<Navbar />
<div className="content" style={{ backgroundColor: '#f4f3ef' }}>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/reports" component={ReportMain} />
<Route path="/showWebService" component={ShowWebService} />
</Switch>
</div>
</div>
The navbar is static when you navigate to link its only getting these component render.
<Link to="/reports">
<p>Reports</p>
</Link>
Call component with Link

Related

How do I make react router v6 load elements without having to manualy refresh the url?

When I send the user to a URL (in this case /login and /signup and then back to /)
the elements on my page don't load automatically by entering the URL, I instead have to manually refresh in order for the content to load.
This is my index.js which handles the routes (with react router v6)
import Navbar from "./components/navbar/navbar";
import Footer from "./components/footer/footer";
import Home from "./pages/home/home";
import Login from "./pages/user/login/login";
import Signup from "./pages/user/signup/signup";
ReactDOM.render(
<div>
<Navbar />
<BrowserRouter>
<Routes>
<Route index path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<Signup />} />
</Routes>
</BrowserRouter>
<Footer />
</div>,
document.getElementById("root")
);
This is an example of what happens when I send the user to /login with the use of the Link component that I am importing through React-router.
Before refreshing the URL on /login
I then have to manually reload the page by pressing the reload button, only after doing so the content will load.
After refreshing the URL on /login
the same applies if I try to go back to the homepage using the Link component
Before refreshing on the URL /
I then have to reload in order to remove the login box
After refreshing on the URL /
I reproduced the same behavior. CodeSandbox (try it and look at home.js)
You don't seem to be using the page navigation correctly. The most react way is to use the useNavigation() hook.
If navigation is working but the routes aren't then I suspect you are rendering them into separate routers. I notice you render the Navbar outside your BrowserRouter, and since navigation is working and updating the URL in the address bar is fairly safe to assume those links are correctly wrapped in a router. You'd see an invariant warning/error otherwise.
ReactDOM.render(
<div>
<Navbar /> // <-- must have another router if it is working
<BrowserRouter>
<Routes>
<Route index path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<Signup />} />
</Routes>
</BrowserRouter>
<Footer />
</div>,
document.getElementById("root")
);
You should have only one router wrapping the app and providing the routing context to all Routes, Route, Navigate, Link, etc... components.
Remove any extraneous routers in other components, like NavBar, and move them all to be within the BrowserRouter you are rendering here.
ReactDOM.render(
<BrowserRouter>
<Navbar />
<Routes>
<Route index path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<Signup />} />
</Routes>
<Footer />
</BrowserRouter>,
document.getElementById("root")
);

How to configure the Routes in Sidebar navigation after Login page in React?

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

How to route to another parent route from a nested route in react-router

I'm having a Parent Container like this:
<Router>
<Switch>
<Route path="/website" component={Website} />
<Route path="/dashboard" component={Dashboard} />
</Switch>
</Router>
And both the Website and Dashboard components has another set of routes.
<Router>
<Switch>
<Route path="/page-one" component={PageOne} />
<Route path="/page-two" component={PageTwo} />
</Switch>
</Router>
//dash
<Router>
<Switch>
<Route path="/dash-page-one" component={DashOne} />
<Route path="/dash-page-two" component={DashTwo} />
</Switch>
</Router>
And Inside PageOne again, I have a child component, from where I want to navigate to <Dashboard /> (another parent) component but it didn't leave the current page, but the route changed.
function(){
<Link to="/dashboard">
Go to dashboard.
</Link>
}
You should only render the router component once by wrapping it around the root of your app, than you should be able to split the the routes navigating to anything inside the router. By creating separate router instances you are in essence creating separate routing environments.

How to load first menu item by default with a different Router Link

I have React Router setup in my Reactjs Project. The header Component has 4 different menu items. After login, I am getting only header component rendered but not first menu item component below it.
I have created a Homepage component which loads Header component and below that I gave Routes for different menu item pages. In the Header component for every Item, I linked it to the corresponding Item Page.
//Home Page Code.
<Router>
<Header />
<Route path='/Jobs' component={Jobs} />
<Route path='/Admin' component={Admin} />
<Route path='/Requests' component={Requests} />
</Router>
To use react router you have to wrap your routes in switch.
Switch will render the first item that matches the current route.
Because you have no switch, the routes are ignored.
To render a default site, change the path of the last route to / and it will match everything.
By setting it as last element, it will always be rendered, if no other route above matches the current route.
<Router>
<Header />
<Switch>
<Route path='/Jobs' component={Jobs} />
<Route path='/Admin' component={Admin} />
<Route path='/' component={Requests} />
</Switch>
</Router>
Hope this helps. Happy coding.
Try putting <Switch></Switch> container around your routes:
//Home Page Code.
<Router>
<Header />
<Switch>
<Route exact path='/' component={Home} />
<Route path='/Jobs' component={Jobs} />
<Route path='/Admin' component={Admin} />
<Route path='/Requests' component={Requests} />
</Switch>
</Router>
Edited: to add path for home (path='/')

React Router v4 nested route to change the entire content

I have been trying to understand how to apply the concept of nested routes to my scope.
I need these routes:
/projects
Title
List
NavLink to /projects/new
This route will have a list of projects and a button to create a new project.
/projects/new
Form
NavLink to close and go to /projects
When this route is called, will appear a panel above the content, it doesn't change the page projects.
/projects/:projectId/dashboard
Dashboard Title
List of items
When a project is selected, I need to show its dashboard in a whole new page, different than the /projects
My react route config:
<Switch>
<Route exact path='/home' component={Home}/>
<Route path='/home' component={Home}/>
<Route path='/projects' component={Projects} />
<Redirect to="/home" push />
</Switch>
My render inside projects to receive the other route:
<section className='content projects'>
<div>
<h3>List</h3>
<ul>{list}</ul>
</div>
<Route path='/projects/new' render={
() => {
return <div>
<h3>New Project</h3>
<form action="#">
<input type="text" placeholder='Contract name'/>
<input type="text" placeholder='Project name'/>
<button type="submit">Create</button>
</form>
<NavLink to='/projects'>Close</NavLink>
</div>
}
} />
</section>
Now, where should I put this route:
<Route path='/projects/:projectId/dashboard' component={Dashboard} />
I thought if I put inside the switch, would work, but the page gets blank.
Anyone can help me with this? =)
Thanks!
UPDATE 1
I tried to put my dashboard route above /projects with exact.
Now I'm getting a blank content where it should appear the Dashboard component. The route for projects is still working normally.
<Switch>
<Route exact path='/' component={Home}/>
<Route exact path='/projects/:projectId/dashboard' render={ () => {
return <h2>Dashboard</h2>
}} />
<Route path='/projects' component={Projects} />
<Redirect to="/home" push />
</Switch>
UPDATE 2
I have created a separated project and it worked with the answer in this topic. Now I will try to figure out why it didn't work in the project that I'm having blank page.
Try adding the exact prop to the Route and make sure that it appears BEFORE /projects in the Switch:
<Switch>
<Route exact path='/home' component={Home}/>
<Route path='/home' component={Home}/>
<Route exact path='/projects/:projectId/dashboard' component={Dashboard} />
<Route path='/projects' component={Projects} />
<Redirect to="/home" push />
</Switch>
What's happening is your first /projects is matching any route that starts with /projects. Adding the exact prop will make sure that if the route matches /projects/:projectId/dashboard exactly, it will render Dashboard.

Categories

Resources