Reputation: 461
Here's a working code:
const AppRouter = () => (
<BrowserRouter>
<div>
<Header />
<Switch>
<Route path="/" component={DashboardPage} exact={true} />
<Route path="/:id" component={ViewerPage} /> // <-- Exclude Header component from this page
<Route path="/create" component={CreatePage} />
<Route path="/edit/:id" component={EditPage} />
<Route path="/help" component={HelpPage} />
<Route component={NotFoundPage} />
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;
I couldn't seem to figure out how to exclude the Header component from ViewerPage component page. Is there any way to do this?
Upvotes: 9
Views: 11689
Reputation: 179
In your Router file call useRouteMatch() before a <Switch>
export Routes = (
{useRouteMatch("/specific-route")?.isExact ? (
<Header />
) : null}
<Switch>
<Route path="other/path" component={Other}
...
</Switch>
);
Alternatively, call withRouter() to have direct access to match
, location
and history
.
export const AuthenticatedRoutes = withRouter(() => (
{location.pathname !== `/special-url` ? (
<Header />
) : null}
<Route path="/special-url" component={Special}
<Route path="/other" component={Other}
));
export Routes = (
{useRouteMatch("/specific-route")?.isExact ? (
<Header />
) : null}
<Switch>
<Route component={AuthenticatedRoutes}
</Switch>
);
Upvotes: 0
Reputation: 3887
Had the exact same requirement in my last project and I went with the approach of splitting the header out into its own component and the using React Fragments. Idiomatic!
import React, { Fragment } from 'react'
// ...
const App = () => (
<div>
<Switch>
<Route path='/no-header-route' component={NoHeaderComponent} /> // Route without header
<Fragment> // This is the key
<Header/> // Header is in its own component
<Route path='/route-1' component={Comp1}/> // Route with header
<Route path='/route-2' component={Comp2}/> // Route with header
</Fragment>
</Switch>
</div>
)
Upvotes: 22
Reputation: 5645
The withRouter Higher-order-Component provided by the react-router
package will give you access to the location object. Once you have that you can conditionally render the header by short-circuiting.
import {withRouter} from 'react-router'
const App = ({location}) => (
<div>
{location.pathname !== '/exclusion-path' && <Header/>}
<Switch>
...
</Switch>
</div>
)
export default withRouter(App)
or to exclude on multiple paths...
const exclusionArray = [
'/path-one',
'/another-path',
]
const App = ({location}) => (
<div>
{exclusionArray.indexOf(location.pathname) < 0 && <Header/>}
<Switch>
...
</Switch>
</div>
)
If you're doing anything serious I'd recommend using the context api and short-circuit on a value provided by context. If this is the case and you need some direction I'd be happy to explain it to you.
P.S. If you want to do it with the alpha Hooks API I'll get really excited.
EDIT: To address commont.
Move your Router outside of the App component.
import {BrowserRouter as Router} from 'react-router-dom'
import ReactDOM from 'react-dom'
ReactDOM.render(
<Router>
<App/>
</Router>,
document.getElementById('render-target')
)
Upvotes: 11
Reputation: 473
1- something like, In Header.js
import {withRouter} from 'react-router-dom';
class Header extends Component {
render() {
if (this.props.location.pathname === '/') {
return null
}
return (
// other stuff
);
}
}
export default withRouter(Header);
Note that, withRouter can be different with different react router version. But idea is the same: check your pathname with ViewerPage's pathname, and do not display Header if it is the path...
2- Other approach is do the same thing with 'redux'
so whenever ViewerPage is loaded, dispatch an action. In ViewerPage.js
class ViewerPage extends Component {
componentDidMount() {
this.props.updateShouldDisplayHeader(false);
}
componentWillUnmount(){
this.props.updateShouldDisplayHeader(true);
}
}
In Header.js
class Header extends Component {
render() {
if(!this.props.shouldDisplayHeader) {
return null;
}
return (
// other stuff
);
}
}
I suppose you already know how to create action and use reducers on redux
Upvotes: 0