I'm creating dashboard/admin control panel application in React and I'm not sure how to handle component rendering correctly.
So at first my main App component looks like this:
<React.Fragment>
<div className="main--container">
<HashRouter>
<Redirect exact from="/" to="/login"/>
<Route exact path="/login" component={Login}/>
<Route exact path="/register" component={Register}/>
<Route exact path="/dashboard" component={Dashboard}/>
</HashRouter>
</div>
</React.Fragment>
And it works great, but after user is logged in I'm redirecting him to /dashboard where I want to nest other routes like /dashboard/foo or /dashboard/goo/
My dashboard component:
<React.Fragment>
<Sidebar/>
<div className="main--dashboard">
Here I want to render other components.
</div>
<button onClick={this.handleLogout}>Logout</button>
</React.Fragment>
Where <Sidebar/> is going to control which component should render next to the sidebar.
So my question is how to swtich routes and render appropriate components without affecting(Sidebar should be always present) <Sidebar/> component?
You can use like this
Dashboard.js
<React.Fragment>
<Sidebar>
<Login /> //as well <Register /> in Register.js
</Sidebar>
</React.Fragment>
Login.js
<div className="main--dashboard">
// Here you can render your components And also <Sidebar> remains as it is while redirects this.
</div>
<button onClick={this.handleLogout}>Logout</button>
Related
<Routes>
<Route exact path='/'>
<Layout>
<Home></Home>
</Layout>
</Route>
</Routes>
Layout consists of header and footer, I want to wrap my home inside Layout.
React 18.1.0
react-router-dom 6.0.2
Other Route components are the only valid children of a Route component. This is the use case of building nested routes. For routed content/components, these must use the element prop.
Render the Layout component as the element of the Route component.
Example:
<Routes>
<Route
path='/'
element={(
<Layout>
<Home />
</Layout>
)}
/>
</Routes>
It also common to have layout components render an Outlet for nested routes.
Example:
const Layout = () => (
<>
<Header />
<Outlet />
<Footer />
</>
);
...
<Routes>
<Route element={<Layout />}>
<Route path='/' element={<Home />} />
</Route>
</Routes>
You could just extract the <Home/> component from there and provide the layout as a prop to the Route like this
<Route component={Layout} />
And provide your home component inside the Layout component it self
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
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
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.
For some reason the nested routes in my react based application using react-router v4 are not working.
The Dashboard component is rendering 3 child components, namely Header , Footer & Content1 . All of these components render by default on route /dashboard but I want the Content1 component to change according to the url, i.e. Content2 component should render on url /dashboard/content2 in place of Content1 which is not happening and hitting this url throws a 404 error. Any help is highly appreciated. Following is the code:
index.js
return (
<Router>
<div>
<Route exact path="/" component={Login}/>
<Route path="/dashboard" component={Dashboard} />
</div>
</Router>
);
Dashboard.js
return (
<div>
<Header/>
<Footer/>
<Switch>
<Route path="/dashboard/content2" component={Content2} /> // Hitting this route throws a 404 error...
<Route component={Content1} />
</Switch>
</div>
);