I searched a lot on the Web and SO, asked in reactiflux chat, but didn't found a clean and non-hack-looking way of rendering some component depending of route/path.
Let's say I have the <Header />
which should be shown on some pages and should be hidden on other ones.
For sure I can use this string in Header component
if (props.location.pathname.indexOf('/pageWithoutAHeader') > -1) return null
That's totally fine, if /pageWithoutAHeader
is the unique. If I need same functionality for 5 pages it become this:
if (props.location.pathname.indexOf('/pageWithoutAHeader1') > -1) return null
if (props.location.pathname.indexOf('/pageWithoutAHeader2') > -1) return null
if (props.location.pathname.indexOf('/pageWithoutAHeader3') > -1) return null
Yes, I can store routes in the array and write a loop, which will be more code-reusable. But is it a best and the most elegant way to handle this use case?
I believe that it can be even buggy, for example if I don't render header for a page with a route /xyz
and I have routes with UUIDs, like /projects/:id
, and id=xyzfoo
, so /projects/xyzfoo
won't show a header but it should.
You can list all routes without a header first and group others in additional switch:
...
<Switch>
<Route path="/noheader1" ... />
<Route path="/noheader2" ... />
<Route path="/noheader3" ... />
<Route component={HeaderRoutes} />
</Switch>
...
HeaderRoutes = props => (
<React.Fragment>
<Header/>
<Switch>
<Route path="/withheader1" ... />
<Route path="/withheader2" ... />
<Route path="/withheader3" ... />
</Switch>
</React.Fragment>
)
From the documentation:
Routes without a path always match.
Unfortunately this solution might have a problem with "not found" page. It should be placed at the end of the HeaderRoutes
and will be rendered with a Header
.
Dhara's solution doesn't have such problem. But it might not work well with Switch
if React Router internals change:
All children of a
<Switch>
should be<Route>
or<Redirect>
elements. Only the first child to match the current location will be rendered.
HOC over Route
is not a Route
itself. But it should work fine because current codebase in fact expects any React.Element
with the same props semantics as <Route>
and <Redirect>
have.