How to remove a site header from specific pages React - javascript

I have set up a login page for my web app but the site header component I created earlier appears on the top. It has a menu in it that leads to other pages, so if it's on the login page a user doesn't need to login when they can just click the menu option that will lead them to the home page.
I would like the site header to be invisible on the login, register and reset pages.
index.js
return (
<BrowserRouter>
<SiteHeader />
<Routes>
<Route path="/reviews/:id" element={ <MovieReviewPage /> } />
<Route path="/movies/home" element={<HomePage />} />
<Route path="/movies/favorites" element={<FavoriteMoviesPage />} />
<Route path="/movies/upcoming" element={<UpcomingMoviesPage />} />
<Route path="/movies/:id" element={<MoviePage />} />
<Route exact path="/" element={<LoginPage />} />
<Route exact path="/register" element={<RegisterPage />} />
<Route exact path="/reset" element={<ResetPage />} />
<Route path="*" element={ <Navigate to="/" /> } />
</Routes>
</BrowserRouter>
);
};

There are many ways to do that, but personally, I prefer to do so.
export const MyLayout = ({children}) => {
return (
<>
<SiteHeader />
{children}
</>
)
}
And after all, put your PageComponent inside component wherever you need.
For example.
const HomePage = () => {
return (
<MyLayout>
<div> This is Home Page </div>
</MyLayout>
)
}

Add an Authentication Context Provider. You could then read the context and render the header when you're logged in, else not.
https://codesandbox.io/embed/authentication-with-react-context-d3x0r

Related

ReactJS Routing Page Refresh

Currently using ReactJS to construct a small web app. I have the following parent function:
const Main = () => {
return (
<div className="dialog-base">
<BrowserRouter>
<Switch>
<Route exact path="/login" component={Login}></Route>
<Route exact path="/login/forgot_password" component={ForgotPwd}></Route>
<Route exact path="/login/reset_password/:key" component={ResetPwd}></Route>
<Route exact path="/portal" component={Portal}></Route>
</Switch>
</BrowserRouter>
</div>
);
}
and the following is the "Portal" component:
class Portal extends React.Component {
render = () => {
return (
<BrowserRouter basename="/main">
<div className="navmenu">
<NavLink to="messaging" activeClassName="selected">Messaging</NavLink>
<NavLink to="files" activeClassName="selected"></NavLink>
<NavLink to="payledger" activeClassName="selected"></NavLink>
</div>
<div className="apparea">
<Switch>
<Route path="/messaging" component={Messaging}></Route>
<Route path="/files" component={Files}></Route>
<Route path="/payledger" component={PayLedger}></Route>
</Switch>
</div>
</BrowserRouter>
);
}
}
When the portal component is loaded and I refresh the web page, the page goes blank. I am assuming that this has something to do with the nested routing? Any help on how to fix it would be much appreciated.
You don't need two <BrowserRouter />. Just define one <BrowserRouter /> in your top level component.
In react-router-dom v4+ the <Route /> is just like a regular component and you can use it inside your components to render UI when the path matches the URL.
Here is the working codesandbox example.
Make sure not to put exact on your parent <Route /> because when you have child routes like /main/messaging the <Route exact path="/main" /> never gets to render and therefore children of that route can't be rendered also.
You keep your <Main /> component as is but remove the exact from the <Route path='/portal' /> and change the <Portal />.
class Portal extends React.Component {
render = () => {
return (
<React.Fragment>
<div className="navmenu">
<NavLink to="/portal/messaging" activeClassName="selected">Messaging</NavLink>
<NavLink to="/portal/files" activeClassName="selected"></NavLink>
<NavLink to="/portal/payledger" activeClassName="selected"></NavLink>
</div>
<div className="apparea">
<Switch>
<Route path="/portal/messaging" component={Messaging}></Route>
<Route path="/portal/files" component={Files}></Route>
<Route path="/portal/payledger" component={PayLedger}></Route>
</Switch>
</div>
</React.Fragment>
);
}
}

Using material ui tabs with react router?

I have a project in react/typescript. I have a react router that looks like this
const Root = () => (
<>
<NavBar/>
<Router>
<Route path="/" component={Home} />
<Route path="/timer" component={TimerPage} />
</Router>
</>
);
And I have a material-ui appbar that looks like this
export default function NavBar() {
return (
<div>
<AppBar position="static">
<Tabs>
<Tab label="Timer" to="/timer" component={TimerPage} />
</Tabs>
</AppBar>
</div>
);
}
There are a few issues - first the 'to' in Tab doesn't compile. Secondly, how do I make these two components work together, given they do very similar things?
If you are trying to navigate to another page, wrap your tab component, let react-router handle with the navigation and navigate using react-router history,
<Tabs value={value} onChange={handleChange} aria-label="simple tabs
example">
<div onClick={() => history.push("/timer")}>
<Tab label="Timer" />
</div>
</Tabs>
<Router>
<Route path="/" component={Home} />
<Route path="/timer" component={TimerPage} />
</Router>
Route should be inside Switch. Also, if you write path="/" this means that whatever page you will visit will still go to "home" page. This is because react-router does something like "least" checking of routes. So, if you had defined path "/images", before "/images/1", both will route you to "/images". Instead you could change the order of these paths, or add exact keyword before the first one.
Take a look at example below.
<Router>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/timer" component={TimerPage} />
</Switch>
</Router>
or
<Router>
<Switch>
<Route path="/timer" component={TimerPage} />
<Route path="/" component={Home} />
</Switch>
</Router>
As for your second issue, you should put your AppBar (or div or any container) inside Router and assign Link to component property of Tab:
<Router>
<AppBar position="static">
<Tabs>
<Tab label="Timer" to="/timer" component={Link} />
</Tabs>
</AppBar>
</Router>
Keep in mind that Link component is imported from react-router and not from #mui.

Hide specific components for a route using React Router

In my code, I want Header & Footer components to be rendered in all routes except '/login'so how to do that? How to hide component on a specific route?
const AppRouter = () => {
return (
<BrowserRouter>
<div>
<Header />
<Switch>
<Route path="/login" component={Login} /> {/* I wanna render this route without Header & Footer */}
<Route path="/" component={Home} exact />
<Route path="/product" component={ProductOverview} />
<Route path="/profile" component={Profile} />
<Route component={NotFound} />
</Switch>
<Footer />
</div>
</BrowserRouter>
);
};

Unable to render react components upon clicking the Links

I have a react application in which I have wrapped layout components for the other routes, the thing is when I click the links present in the sidebar(part of layout) they are not being rendered on the screen, here is my code.
App.js
//Imports here
<Provider store={store}>
<Router>
<Switch>
<Layout>
<Route exact path="/admin" render={() => <Admin />} />
<Route exact path="/employees" render={() => <Employees />} />
<Route exact path="/profile" component={Profile} />
</Layout>
<Switch>
</Router>
</Provider>
Layout.js
//imports here
//styling here
<Link to='/employees' />
// and likewise for rest of the routes
When clicking the links ie, employees or profile they aren't being rendered, tried console.log to see if my layout was obstructing that, but no use. Please help me
It should be inside the Switch component but you can wrap it with a Layout component like that.
const Headers = () => (
<Layout>
<ul>
<li>
<Link to="/admin">Admin</Link>
</li>
<li>
<Link to="/profile">Profile</Link>
</li>
<li>
<Link to="/employees">Employees</Link>
</li>
</ul>
</Layout>
);
function App() {
return (
<Router>
<Layout>
<Header></Header>
<Switch>
<Route exact path="/admin" render={() => <Admin />} />
<Route exact path="/employees" render={() => <Employees/>}/>
<Route exact path="/profile" component={Profile} />
</Switch>
</Layout>
</Router>
);
}
If your URL is changing but the content is not being rendered, the problem is this, apart from wrapping the Routes as mentioned in #G.aziz 's answer since the routes are children WRT layout components we have to use {props.children} inside the layout component to render the content like so...
Layout.jsx
<div>
<Sidebar />
<Navbar />
{props.children} // here we are rendering the routes which we mentioned in the switch component in App.js
</div>
For me this solution fixed. Also please refer this question for further information. React-router v4, URL changing but component doesn't render

How do I nest routes with React router

I have multiple layouts that should include different screens. Each layout has its own header, footer, and other things similar pages should share. Here is the code I came up with:
<BrowserRouter>
<Route path={['/index', '/about']} component={BaseLayout}>
<Route path="/index" component={Index} />
<Route path="/about" component={About} />
</Route>
<Route path={['/sign-in', '/sign-up']} component={AuthLayout}>
<Route path="/sign-in" component={SignIn} />
<Route path="/sign-up" component={SignUp} />
</Route>
<Route path={['/stats'} component={DashboardLayout}>
<Route path="/stats" component={Stats} />
</Route>
</BrowserRouter>
The code above obviously won't work because:
Warning: You should not use <Route component> and in
the same route; <Route component> will be ignored
Answers to similar questions on SO suggest to use wrapper components directly:
<BrowserRouter>
<BaseLayout>
<Route path="/index" component={Index} />
<Route path="/about" component={About} />
</BaseLayout>
<AuthLayout>
<Route path="/sign-in" component={SignIn} />
<Route path="/sign-up" component={SignUp} />
</AuthLayout>
<DashboardLayout>
<Route path="/stats" component={Stats} />
</DashboardLayout>
</BrowserRouter>
Problem with this approach is that even that it renders a single screen, it also renders elements from the other layouts, i.e. if you're on the index page rendered inside the BaseLayout, you will see elements from the AuthLayout and DashboardLayout too. Which kinda makes sense because they are not wrapped in a Route.
Some people suggested to grab the content of all layouts and add them as siblings to the current Routes. However this is a mess to me. I do want to keep all layouts in separate files and only pass screens as children to them.
This is a rough draft of a potential layout structure:
<Header>
<Route>
<Route path={['/index', '/about']} component={HeaderComponent} />
<Route path={['/sign-in', '/sign-up']} component={AuthHeaderComponent} />
</Route>
</Header>
<Screens>
<Route>
<Route path="/index" component={BaseLayout(Index)} />
<Route path="/about" component={BaseLayout(About)} />
<Route path="/sign-in" component={AuthLayout(SignIn)} />
<Route path="/sign-up" component={AuthLayout(SignUp)} />
<Route path="/stats" component={DashboardLayout(Stats)} />
</Route>
</Screens>
<Footer>
<FooterComponent />
</Footer>
In this example the wrappers are HOCs so they can handle passing all props from the route down to the page component, but if you just wanted to do an inline wrapper you could use the render function:
<Route
path="/index"
render={routeProps => {
return (
<BaseLayout>
<Index {...routeProps}/>
</BaseLayout>
);
}}
/>
[edit] A sample Layout HOC (docs)
const withBaseLayout = WrappedComponent => {
// any business logic required for the layout
// layoutProps, style, etc...
return (
<BaseLayout {...layoutProps}>
<WrappedComponent {...this.props} /> // these are all the passed in props
// you can inject more props into Wrapped component as well
// i.e. redux's connect or react-router-dom's withRouter HOCs
</BaseLayout>
);
}
// in index.js
export default withBaseLayout(Index);
// in route
<Route path="/index" component={Index} /> // already wrapped
Or directly as Component
const BaseLayoutHOC = WrappedComponent => {
// any business logic required for the layout
// layoutProps, style, etc...
return (
<BaseLayout {...layoutProps}>
<WrappedComponent {...this.props} />
</BaseLayout>
);
}
// in route
<Route path="/index" component={BaseLayoutHOC(Index)} />

Categories

Resources