App.js
function App() {
<div className="App">
<Router>
<Switch>
<Route exact path="/home" component={Home} />
<Route exact path="/search" component={Home} />
</Switch>
</Router>
</div>;
}
Home.js
function Home() {
const location = useLocation();
return (
<div className="home">
<Component1 />
{location.pathname === "/home" && <Feed />}
{location.pathname === "/search" && <Search />}
<Component2 />
</div>
);
}
This works perfectly as I want to render the Feed or Search component depending on the URL.
But, I want to know is it okay to use location.pathname or is there any better alternative?
You could do something like:
App.js
function App() {
return <div className="App">
<Router>
<Switch>
<Route exact path="/home" component={() => <Home showFeed/>} />
<Route exact path="/search" component={() => <Home showSearch/>} />
</Switch>
</Router>
</div>;
}
Home.js
function Home(props) {
const location = useLocation();
return (
<div className="home">
<Component1 />
{props.showFeed && <Feed />}
{props.showSearch && <Search />}
<Component2 />
</div>
);
}
This allows you to abstract away the Home component's dependency on any routing mechanism, and simply allows you to control whether certain elements appear or not from outside this component.
use home component as layout. This can be highly recommended. You can rename your home component as Layout. This is more flexible way.
function Home() {
const location = useLocation();
return (
<div className="home">
<Component1 />
{ props.children }
<Component2 />
</div>
);
}
In your app.js modify like bellow
function App() {
<div className="App">
<Router>
<Switch>
<Route exact path="/home">
<Home>
<Feed />
</Home>
</Route>
<Route exact path="/search">
<Home>
<Search/>
</Home>
</Route>
</Route>
</Switch>
</Router>
</div>;
}
Related
Why my outlet is not working in react-router-dom. All my components worked fine until I use Outlet and after using outlet my navigation component is not showing while other component seems to render.
import Home from "./Routes/Home/Home.component";
import { Routes, Route, Outlet } from "react-router-dom";
const Navigation = () => {
return (
<div>
<div>
<h1>Hello I am Navigation!!!</h1>
</div>
<Outlet />
</div>
);
};
const Shop = () => {
return <h2>I am shop component</h2>
}
const App = () => {
return (
<Routes>
<Route path='/' element={<Navigation />} />
<Route index element={<Home />} />
<Route path='shop' element={<Shop />} />
</Routes>
);
};
export default App;
I am receiving this:
enter image description here
and I want navigation component to render all above and persist every time I navigate to elsewhere.
for using of Outlet you need Add children to Route Component
const App = () => {
return (
<Routes>
<Route path='/' element={<Navigation/>}>
<Route path="url1" element{<ChildElemnt1 />} />
<Route path="url2" element{<ChildElemnt2 />} />
<Route path="url3" element{<ChildElemnt3 />} />
...
</Route>
<Route index element={<Home />} />
<Route path='shop' element={<Shop/>}/>
</Routes>
);
};
The Navigation component isn't rendered as a layout route with nested routes, so nothing is rendered into the Outlet it is rendering. Navigation will also only render on path "/".
If you want the Navigation component to render always then you can render it alone outside the routes.
const Navigation = () => {
return (
<div>
<div>
<h1>Hello I am Navigation!!!</h1>
</div>
</div>
);
};
const App = () => {
return (
<>
<Navigation />
<Routes>
<Route path='/'>
<Route index element={<Home />} />
<Route path='shop' element={<Shop />} />
</Route>
</Routes>
</>
);
};
Or you can utilize it as a layout route such that it wraps nested routes that render their element into the Outlet.
const Navigation = () => {
return (
<div>
<div>
<h1>Hello I am Navigation!!!</h1>
</div>
<Outlet />
</div>
);
};
const App = () => {
return (
<Routes>
<Route path='/' element={<Navigation />} />
<Route index element={<Home />} />
<Route path='shop' element={<Shop />} />
</Route>
</Routes>
);
};
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>
)
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 am new to react development. And I want to implement the routing mechanism in my page.
For example, there's component contains routes with the <Home /> and <Login /> component.
function App() {
return (
<div className="App">
<Switch>
<Route exact path="/home">
<Home />
</Route>
<Route path="/login">
<Login />
</Route>
</Switch>
</div>
);
}
The <Home /> component contains a <Navbar /> and a <Switch /> with two <Route />:
Home.js
function Home() {
return (
<div>
<Navbar />
<div>
<Switch>
<Route exact path={`/home`}>
<Menu />
</Route>
<Route path={`/home/temperature`}>
<div>temperature</div>
</Route>
</Switch>
</div>
</div>
)
}
However, I defined the <Link /> in the <Menu /> component as below:
function Menu() {
return (
<div>
<li>
<Link to={`/home/temperature`}>temperature child page</Link>
</li>
</div>
)
}
Originally, the page would displayed the <Home /> component with <Menu /> and <div> temperature </div>
I expected that when I clicked the link (<Link to={/home/temperature}>temperature child page</Link>) then it would replace the <Menu /> component with the only the <div>temperature</div> (Dispalyed the <Navbar/> and <div>temperature</div>, but it could not display anything.
How should I correct it?
Solution:
I finally figure out why I cannot get child component in my js script.
Firstly, I need to wrap the <Switch> with <Router> in <App> component.
Then, by reference this , I realized that I should not specify the exact in <Route path="/home"> to make sure that the nested route can work as well.
function App() {
return (
<div className="App">
<Router>
<div>
<Switch>
<Route path="/home">
<Home />
</Route>
<Route path="/login">
<Login />
</Route>
</Switch>
</div>
</Router>
</div>
);
}
simple routing
<Router>
<Switch>
<Route path={"/home"} exact component={Home} />
</Switch>
</Router>
nested routing
<Router>
<Switch>
<Route path={"/home"} exact component={Home}
<Rout path={"/temperature"} exact component={Temperature} />
</Route>
</Switch>
</Router>
`
I have problem with nested routing.
On the normal site I have other urls than on the / admin page and i have different design and html.
I prepared this sample routing but after the page refreshes, the page gets white without any error.
Can I ask for a consultation what did I do wrong?
APP COMPONENT
class App extends Component {
render() {
return (
<BrowserRouter>
<div className="container">
<Route exact path="/" render={(props) => (
<Page {...props} data={data} />
)} />
<Route exact path="/admin" render={(props) => (
<Admin {...props} data={data} />
)} />
</div>
</BrowserRouter>
);
}
}
PAGE COMPONENT
class Page extends React.Component {
render() {
return (
<BrowserRouter>
<div>
<Header />
<Route exact path="/" render={(props) => (
<Home {...props} videosJson={this.props.data} />
)} />
<Route path="/about" component={ About } />
<Route exact path="/video" render={(props) => (
<VideoGallery {...props} videosJson={this.props.data} />
)} />
<Route path="/video/:id" render={(props) => (
<VideoPage {...props} videosJson={this.props.data} />
)} />
<Route exact path="/photo" render={(props) => (
<PhotoGallery {...props} videosJson={this.props.data} />
)} />
<Route path="/photo/:id" render={(props) => (
<PhotoPage {...props} videosJson={this.props.data} />
)} />
<Route path="/contact" component={ Contact } />
<Footer />
</div>
</BrowserRouter>
)
}
}
ADMIN COMPONENT
class Admin extends React.Component {
render() {
return (
<BrowserRouter>
<div>
<Route exact path="/admin" render={(props) => (
<Dashboard {...props} />
)} />
</div>
</BrowserRouter>
)
}
}
Your React application which uses React-Router should only have one instance of a Router defined, as stated in the documentation:
The common low-level interface for all router components. Typically
apps will use one of the high-level routers instead
The error you are getting is because you are defining additional routers (in your case there are multiple instances of BrowserRouter) in your Page and Admin components.
Also some of your Routes are ambiguous e.g.
<Route exact path="/" render={(props) => (
<Page {...props} data={data} />
)} />
and:
<Route exact path="/" render={(props) => (
<Home {...props} videosJson={this.props.data} />
)} />
One Route says that root ('/') should navigate to the Page component, the other says that root should navigate to the Home component, hence there is a conflict. Make sure the routes are unique.
I change my approach to this situation but dont work. Url /admin load Header and Footer component although he should not and component Dashboard not load.
Any sugestion?
<BrowserRouter>
<div className="container">
<Page>
<Header />
<Route exact path="/" render={(props) => (
<Home {...props} videosJson={data} />
)} />
<Route path="/about" component={ About } />
<Route exact path="/video" render={(props) => (
<VideoGallery {...props} videosJson={data} />
)} />
<Route path="/video/:id" render={(props) => (
<VideoPage {...props} videosJson={data} />
)} />
<Route exact path="/photo" render={(props) => (
<PhotoGallery {...props} videosJson={data} />
)} />
<Route path="/photo/:id" render={(props) => (
<PhotoPage {...props} videosJson={data} />
)} />
<Route path="/contact" component={ Contact } />
<Footer />
</Page>
<Admin>
<Route exact path="/admin" render={(props) => (
<Dashboard />
)} />
</Admin>
</div>
</BrowserRouter>
Admin Component:
class Admin extends React.Component {
render() {
console.log("ADMIN:", this.props);
return (
<div className="row">
<h1>ADMIN</h1>
{this.props.children}
</div>
)
}
}
Page Component:
class Page extends React.Component {
render() {
console.log("PAGE:", this.props);
return (
<div>
{this.props.children}
</div>
)
}
}