the problem is the following. in the app.js is spelled out Routes and the home component. the home contains a navbar that navigates the site, only if you go to any page, it is drawn on top of the home. And if you switch to the home itself, it will be duplicated. Articles on the internet did not help, as did the addition of exact in route path.
function App() {
return (
<div className="messenger">
<Routes>
<Route path="/home/" element={<Home/>}/>
<Route path="/settings/" element={<Settings/>}/>
<Route path="/login/" element={<Login/>}/>
<Route path="/register/" element={<Register/>}/>
</Routes>
<Home/>
</div>
)
home
export default class Home extends Component {
render() {
return (
<div>
<NavBar/>
<ChatMenu/>
</div>
);
}
}
an example of how it is written in the navbar
export const NavBar = () => {
return (<div className="navbar-cm">
<div className="nav_element">
<Link to="/home">
<img src={homeIMG} className="nav_element"/>
</Link>
</div>
and a few more similar ones
</div>);
};
Issue
You are rendering the Home component again once outside the routes, this is why it's rendered with all routes including twice when on the "/home" path that renders Home.
function App() {
return (
<div className="messenger">
<Routes>
<Route path="/home/" element={<Home />} />
<Route path="/settings/" element={<Settings />} />
<Route path="/login/" element={<Login />} />
<Route path="/register/" element={<Register />} />
</Routes>
<Home /> // <-- always rendered below routed content
</div>
)
}
Solution
Remove the Home component that is out on its own outside the routes.
function App() {
return (
<div className="messenger">
<Routes>
<Route path="/home/" element={<Home />} /> // <-- now only Home component rendered
<Route path="/settings/" element={<Settings />} />
<Route path="/login/" element={<Login />} />
<Route path="/register/" element={<Register />} />
</Routes>
</div>
)
}
Remove <Home /> from the router:
function App() {
return (
<div className="messenger">
<Routes>
<Route path="/home/" element={<Home/>}/>
<Route path="/settings/" element={<Settings/>}/>
<Route path="/login/" element={<Login/>}/>
<Route path="/register/" element={<Register/>}/>
</Routes>
</div>
)
Related
On a project I just started on reactjs, I should hide an element when the url changes. I searched and did not find something useful.
I would like to hide the Sidebar when the url is not Search.
Thanks to anyone who wants to give me a hand.
import React from 'react';
import { Routes, Route } from "react-router-dom";
import 'bootstrap/dist/css/bootstrap.css';
import 'react-bootstrap';
import './App.css';
import NavBarTop from './components/layouts/header/NavBar_top';
import Sidebar from './components/layouts/Sidebar';
import Home from './components/pages/Home';
import Login from './components/pages/Login';
import Register from './components/pages/Register';
import Search from './components/pages/Search';
import E404 from './components/pages/E404';
function App() {
return (
<>
<div>
<NavBarTop />
<div className="container-fluid maincon">
<Sidebar />
<Routes>
<Route path="/" exact element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
<Route path="/search" element={<Search />} />
<Route path="*" element={<E404 />} />
</Routes>
</div>
</div>
</>
);
}
export default App;
I would like to hide the Sidebar when the url is not Search.
Just render the Sidebar only with the Search component instead of unconditionally with everything.
<div>
<NavBarTop />
<div className="container-fluid maincon">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
<Route
path="/search"
element={(
<>
<Sidebar />
<Search />
</>
)}
/>
<Route path="*" element={<E404 />} />
</Routes>
</div>
</div>
If you wanted to render Sidebar with several routes, then create a layout component. Nested/wrapped Route components are rendered into the Outlet component.
import { Outlet } from 'react-router-dom';
const SidebarLayout = () => (
<>
<Sidebar />
<Outlet />
</>
);
...
<div>
<NavBarTop />
<div className="container-fluid maincon">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
<Route element={SidebarLayout}>
<Route path="/search" element={<Search />} />
... other routes to render with sidebar ...
</Route>
<Route path="*" element={<E404 />} />
</Routes>
</div>
</div>
there are multiple ways to do that.. this is only one...
export default function Wrapper() {
const urlWindow = window.location;
console.log(urlWindow.pathname.split("/")[1]);
const acceptedPaths = ["login", "register", "search", "test"];
return (
<>
<div>
navbar
<div className="container-fluid">
<div className="row">
{acceptedPaths.includes(urlWindow.pathname.split("/")[1]) ? (
<>
<Sidebar />
<MainContent />
</>
) : "Show 404 page"}
</div>
</div>
</div>
</>
);
}
const Sidebar = () => {
return <div className="col-md-2">I'm sidebar</div>;
};
const MainContent = () => {
return <div className="col-md-10">I'm main content</div>;
};
Firstly, you need import useLocation in react-router-dom
import { Routes, Route, useLocation } from "react-router-dom";
and call it in App function to get the current URL path which is used to check against /search for hiding/showing SideBar
function App() {
const location = useLocation();
const currentPath = location.pathname
return (
<>
<div>
<NavBarTop />
<div className="container-fluid maincon">
{currentPath === '/search' && <Sidebar />}
<Routes>
<Route path="/" exact element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
<Route path="/search" element={<Search />} />
<Route path="*" element={<E404 />} />
</Routes>
</div>
</div>
</>
);
}
you can use hook named as useSearchParam
const [searchParams, setSearchParams] = useSearchParams();
to get query/url params as string.
I want to put a div inside <Routes> and also Render a <Topbar /> and <Sidebar /> component inside <Routes> without <Route> tag for them.
My code is as follows:-
const App = () => {
return (
<Router>
<Routes>
<Route path="login" element={<Login />} />
<Topbar />
<div className="container">
<Sidebar />
<Route path="/" element={<Home />} />
<Route path="users" element={<UserList />} />
</div>
</Routes>
</Router>
);
};
I want to implement <Topbar /> and <Sidebar /> for all the routes.
But for an exception of login Page (Topbar and Sidebar should not be shown on the login page).
That's why I had put login Route at the top of Topbar and Sidebar.
The console is showing error as:
Uncaught Error: [Topbar] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>
How to implement this functionality?
In react-router-dom v6 only Route and React.Fragment components are valid children for the Routes component.
Use layout components to render the Topbar and Sidebar components along with an Outlet for nested routes for the routes you want to render these components.
Example:
import { Routes, Route, Outlet } from 'react-router-dom';
const Layout = () => (
<>
<Topbar />
<div className="container">
<Sidebar />
<Outlet />
</div>
</>
);
const App = () => {
return (
<Router>
<Routes>
<Route path="/login" element={<Login />} />
<Route element={<Layout />}>
<Route path="/" element={<Home />} />
<Route path="users" element={<UserList />} />
</Route>
</Routes>
</Router>
);
};
Change your routes like below,
you need to check whether user is logged in or not, if user logged in use Tobbar, Sidebar etc, otherwise just return login route
const App = () => {
const [isLogin, setIsLogin] = useState(false)
return (
<Router>
<Routes>
{ isLogin ? <Topbar />
<div className="container">
<Sidebar />
<Route path="/" element={<Home />} />
<Route path="users" element={<UserList />} />
</div> : <Route path="login" element={<Login />} />
</Routes>
</Router>
);
};
// MAIN FUNCTION { APP START }
const App = () => {
return (
<Router>
<Nav />
<Switch>
<Route to="/" exact component={Home} />
<Route to="/login" exact component={Login} />
</Switch>
</Router>
);
};
export default App;
I just want that the Nav component renders everywhere except the login page ??
You can put it inside a route component along with the Home.
<Router> <Switch>
<Route path="/" exact>
<Nav />
<Home />
</Route>
<Route to="/login" exact component={Login} />
</Switch> </Router>
I am trying to hide my header component on login page like following. But this is not working. Please guide how I can do this. Thanks in advance!
class App extends Component {
render() {
var auth = localStorage.getItem("auth")
console.log("app ===>", auth)
return (
<div className="App">
<Header />
<Router>
<LinkBar />
<main>
<Switch>
<Route path="/home">
<Protected cmp={Home}></Protected>
</Route>
<Route path="/shopping">
<Protected cmp={Products}></Protected>
</Route>
<Route path="/login">
<Login />
</Route>
</Switch>
</main>
</Router>
</div>
)
}
}
export default App
Ideally this should work with jsx.
{ auth ? <Header auth={auth}></Header> : null }
or more elegant way
{ auth && (<Header auth={auth}></Header>) }
You can do something like bellow:
function App(){
return(
<Router>
<Switch>
<Route exact path="/" component={Login} />
<Route component={DefaultContainer} />
</Switch>
</Router>
);
}
const DefaultContainer = () => (
<Header />
<Router>
<Switch>
<Route exact path="/home" component={Home} />
<Route exact path="/shopping" component={Shopping} />
</Switch>
</Router>
)
Another post to ask you about a "situation" I am having, which is disappointing as my Router is creating too many refreshs and for the point is actually not to have to refresh part of the page by using React.
I would like the following :
When I go to './' and there is no user connected it shows a homepage (without header and footer)
When I go to './' and I am connected or any other link whether I am connected ot not it should show the relevant page with a Header and a Footer.
So the fact of being not connected does not show header/footer is only true for the './' address.
How I solved it and it is not satisfying because it seems my header is rerendering all the time I change pages even between two pages with Router....
I have a first Router, the AppRouter :
const AppRouter = () => (
<BrowserRouter>
<div className="content">
<Switch>
<Route path="/" component={Index} exact={true} />
<SubRouter />
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;
My index is like that :
export class Index extends React.Component {
render() {
if (this.props.user){
return (
<SubRouter />
)
} else {
return (
<Homepage />
)
}
}
}
So if no user the Homepage is showing if user it goes back to the SubRouter.
SubRouter is like that :
export class SubRouter extends React.Component {
(...)
render(){
return (
<div className="fullpage">
{this.state.inboxOpen ? <Inbox closeInbox={this.closeInbox} oneUserInboxId={this.state.oneUserInboxId} /> : undefined }
<Header openInbox={this.openInbox} closeInbox={this.closeInbox} />
<Switch>
<Route path="/" component={Dashboard} exact={true} />
<Route path="/admin" component={Admin} exact={true} />
<Route path="/account" component={Account} exact={true} />
<Route path="/settings" component={Settings} exact={true} />
<Route path="/faq" component={Faq} exact={true} />
<Route path="/cgv" component={Cgv} exact={true}/>
<Route path="/legal" component={Legal} exact={true}/>
<Route path="/login" component={Login} exact={true}/>
<Route path="/signup" component={Signup} exact={true}/>
<Route path="/notifications" render={() => (<Dashboard notifications={true} />)} exact={true} />
}} />
<Route path="/reset-password/:token" component={ResetPassword} />
<Route path="/forgot_password" component={ForgotPassword} exact={true} />
<Route path="/post/:postId" component={OnePost} />
<Route path="/*" component={NotFound} />
</Switch>
<Footer />
</div>
)
}
}
So this code is "working" but somehow we can see rerenders that should not happen, I am open to any idea to optimize this. Thanks in advance !
Problem was coming from here :
const AppRouter = () => (
<BrowserRouter>
<div className="content">
<Switch>
<Route path="/" component={Index} exact={true} />
<SubRouter />
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;
Should not have rerendered SubRouter here as it is already rendered in HomePage. Good code is :
const AppRouter = () => (
<BrowserRouter>
<div className="content">
<Switch>
<Route path="/" component={Index} exact={true} />
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;