To hide the navbar on the home component I am doing the following
const NavbarComponent = (props) => {
console.log(props);
if (props.match.path === '/') {
return null;
} else
return (
it works fine, I need to have access to the router so I can send people to locations dependant on the props object , is there a better way to do it such that I have all router logic in the same place?
this is the current state of my router
return (
<div>
<Router>
<Route component={Navbar} />
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/api/:city/electronics" component={Electronics} />
<Route exact path="/api/:city/labour" component={Labour} />
<Route exact path="/api/posts/item/:id" component={ItemDetails} />
<Route exact path="/create/:city/:category" component={CreatePost} />
</Switch>
</Router>
</div>
);
thanks for your time.
I'm not sure I understand why your NavBar component is in it's own Route. Any components contained within the Router have access to the entire Router api, including Link - they do not need to be a Route to do so.
I would suggest wrapping all the Routes that include the NavBar with that component. The Routes will then be displayed as children of the Navbar component.
Here is a simplified example:
// App.js
return (
<div>
<Router>
<Switch>
<Route exact path="/" component={Home} />
<NavBar>
<Route exact path="/electronics" component={Electronics} />
<Route exact path="/labour" component={Labour} />
</NavBar>
</Switch>
</Router>
</div>
);
//NavBar.js
return (
<>
<div>
<Link to="/electronics">Electronics</Link>
<Link to="/labour">Labour</Link>
</div>
<div>{props.children}</div>
</>
);
codesandbox
Related
I'm having to trouble making a route without layout component. Please check my code first.
// App.js
const App = () => {
return (
<div className={styles.container}>
<Header />
<main>
<QuizBoxContainer>
<Routes>
<Route path='/' element={<QuizSelect />} />
<Route path='quiz-for/:language' element={<QuizCard />} />
<Route path='result' element={<ResultPage />} />
</Routes>
</QuizBoxContainer>
<Routes>
<Route path='wrong-answer' element={<WrongAnswer />} />
</Routes>
</main>
</div>
)
}
In the code, <QuizBoxContainer> is the layout component.
What I was trying to do is making another path,
<Routes>
<Route path='wrong-answer' element={<WrongAnswer />} />
</Routes>
outside of <QuizBoxContainer> so I can use another layout on this component.
However, when I go to WrongAnswer,
It still renders.
What is wrong with my code, and how can I solve it?
Issue
The is because the QuizBoxContainer layout wrapper component is not rendered on any route, it's always rendered.
Solution
Move QuizBoxContainer into a layout route. You'll need to update QuizBoxContainer so it renders an Outlet component instead of the children prop.
Example:
import { Outlet } from 'react-router-dom';
const QuizBoxContainer = () => {
...
return (
... quiz container layout/styling ...
<Outlet /> // <-- nested routes render content here
...
);
};
Render QuizBoxContainer on a layout route wrapping the routes you want to render within it, render the wrong answer route outside the layout route.
const App = () => {
return (
<div className={styles.container}>
<Header />
<main>
<Routes>
<Route element={<QuizBoxContainer />}>
<Route path='/' element={<QuizSelect />} />
<Route path='quiz-for/:language' element={<QuizCard />} />
<Route path='result' element={<ResultPage />} />
</Route>
<Route path='wrong-answer' element={<WrongAnswer />} />
</Routes>
</main>
</div>
)
}
How do i hide certain components on certain pages in my app?
Specifically I need to hide Navbar and Header from the Settings page.
in App.js i set up a router:
<div>
<Router>
<Switch>
<Header/> <- header and navbar are here
<Navbar/>
<Route exact path = "/" component= { Data } />
<Route path = "/available-data" component= { Data } />
<Route path = "/devices" component= { Devices } />
<Route path = "/contacts" />
<Route path = "/chat" />
<Route path = "/settings" component = { Settings } /> <- i need to remove them from here
</Switch>
</Router>
</div>
Header and Navbar are used in every component except in Settings. How do i go about removing/hiding them?
All three of the files are function components with useState hooks(if they even have state) if it matters :)
You can render a second switcher component to only route to pages with the header and navbar UI.
// in App.js
<div>
<Router>
<Switch>
<Route exact path="/settings" component={Settings} />
<Route path='/' ><UiRouter /></Route>
</Switch>
</Router>
</div>
// in UiRouter.js
export default function UiRouter() {
return (
<>
<Header />
<Navbar />
<Switch>
<Route exact path="/" component={Data} />
<Route path="/available-data" component={Data} />
<Route path="/devices" component={Devices} />
<Route path="/contacts" component={Contacts}/>
<Route path="/chat" component={Chat}/>
</Switch>
</>
);
}
Also, as Ajith mentioned, you should not have the components that you want to render for each route (Header and Navbar) inside the Switch component.
I have a Search component, when the homepage component is rendered I'd like the Search component to be rendered at the bottom of the page. When any other page component is rendered I'd like the Search component to be at the top of the page.
Currently what I have my app.js as:
const App = () => {
return (
<BrowserRouter>
<Switch>
<Route path='/' component={Home} />
<Route path='/about' component={About} />
<Route path='/work' component={Work} />
<Route path='/contact' component={Contact} />
</Switch>
</BrowserRouter>
)
}
and inside a page component:
const Contact = () => {
return (
<div>
<Search />
Contact
</div>
)
}
Obviously this way means I have to add the Search component to every component and choose whether I place it at the top or bottom.
My question is this, can I place it on the app.js like so:
const App = () => {
return (
<BrowserRouter>
<Search />
<Switch>
<Route path='/' component={Home} />
<Route path='/about' component={About} />
<Route path='/work' component={Work} />
<Route path='/contact' component={Contact} />
</Switch>
</BrowserRouter>
)
}
And then depending on which page component is being rendered, style the Search component so it either appears at the top or bottom of the page.
Thanks
I would add a className prop to the Search component and add some if statement.
For example:
<Search className={location === '/' ? 'top' : 'bottom'} />
With the useLocation() hook provided by React Router, you can determine what page you're on.
const Contact () => {
const location = useLocation();
const styles = location === "something" ? {...topStyles} : {...downStyles};
return (
<div>
<Search style={styles} />
Contact
</div>
)
}
Being a beginner in reactJS, I want to know how to hide parent component when i route to child component URL
Assume a scenario:
User is at "/house" as this:
<Route path="/house" component={House} />
when user clicks a house grid he navigates to "/house/flat/:flatID". Inside House component
<Route
path={`${this.props.match.url}/flat/:flatId`}
render={() => <div>Each Flat details</div>}
/>
then both child and parent components are visible like this:
So what i want is to show only flat component when user navigates to "/house/flat:FlatId". Please suggest me anything that helps ! Any links to article so that i can learn and achieve such functionality.
Code:
App.js
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/account" component={Account} />
<Route path="/gharjagga" component={GharJagga} />
</Switch>
House.js
onGharGridClick= id => {
<Redirect to={`${this.props.match.url}/flat/${id}`} />;
};
return (
<Route
path={`${this.props.match.url}/flat/:fkatId`}
render={() => <div>Ghar Each</div>}
/>
);
You can achieve it different ways
define routes in the parent component, I think this is the best option.
<Switch>
<Route path="/account" component={Account} />
<Route path="/house/flat/:flatId" component={FlatComponent}/>
<Route path="/house" component={House} />
<Route path="/" component={Home} />
</Switch>
Note: instead of using exact, order your routes based on priority, that will make the route to redirect to next matching route if any typo in the route entered
You can make House as separate route component, and nest the routes inside that component
// Routes
<Switch>
<Route path="/account" component={Account} />
<Route path="/house" component={House} />
<Route path="/" component={Home} />
</Switch>
// House component
class House extends React. Components {
render() {
return (
<Switch>
<Route path="/house/flat/:flatId" render={() => <div>Each Flat details</div>} />}/>
<Route path="/house" component={HouseGridComponent} />
</Switch>
)
}
}
you can check whether the route has flatId and hide the elements, in your House component you can check this.props.match.params.flatId, if the flatId is set you can hide that House Component.
// House Component
class House extends React. Components {
render() {
return (
<div>
{
!this.props.match.params.flatId?
<h1>House Component</h1>:
null
}
<Route path={`${this.props.match.url}/flat/:flatId`} render={() => <div>Each Flat details</div>} />
</div>
)
}
}
The solution is to raise "/house/flat/:flatId" to the same level as "/house".
<Switch>
<Route exact path="/" component={Home} />
<Route path="/account" component={Account} />
<Route path="/house/flat/:flatId" render={() => <div>Each Flat details</div>}/>
<Route path="/house" component={House} />
</Switch>
I am trying to group some of my routes together with React Router v4 to clean up some of my components. For now I just want to have my non logged in routes group together and my admin routes grouped together but the following doens't work.
main.js
const Main = () => {
return (
<main>
<Switch>
<Route exact path='/' component={Public} />
<Route path='/admin' component={Admin} />
</Switch>
</main>
);
};
export default Main;
public.js
const Public = () => {
return (
<Switch>
<Route exact path='/' component={Greeting} />
<Route path='/signup' component={SignupPage} />
<Route path='/login' component={LoginPage} />
</Switch>
);
};
export default Public;
The Greeting component shows at "localhost:3000/", but the SignupPage component does not show at "localhost:3000/signup" and the Login component doesn't show at "localhost:3000/signup". Looking at the React Dev Tools these two routes return Null.
The reason is very obvious. for your route in main.js, you have specified the Route path of Public component with exact exact path='/' and then in the Public component you are matching for the other Routes. So if the route path is /signup, at first the path is not exact so Public component is not rendered and hence no subRoutes will.
Change your route configuration to the following
main.js
const Main = () => {
return (
<main>
<Switch>
<Route path='/' component={Public} />
<Route path='/admin' component={Admin} />
</Switch>
</main>
);
};
export default Main
public.js
const Public = () => {
return (
<Switch>
<Route exact path='/' component={Greeting} />
<Route path='/signup' component={SignupPage} />
<Route path='/login' component={LoginPage} />
</Switch>
);
};
Also when you are specifying the nested routes these should be relative to the parent Route, for instance if the parent route is /home and then in the child Route you wish to write /dashboard . It should be written like
<Route path="/home/dashboard" component={Dashboard}
or even better
<Route path={`${this.props.match.path}/dashboard`} component={Dashboard}