When a ReactJS application is developed, most of us come across the requirement to display a 404 page for all invalid paths. With frameworks such as AngularJS, it’s just a matter of adding another route with double-asterisk wildcard (**
). But with ReactJS hash routing, it’s a bit different and let’s see how it can be done.
For this article, let’s consider a very basic React app with only one component that provides login. When a user accesses the path /#/login
, this login component should be displayed. To achieve that, we can define our router configuration as follows.
<HashRouter>
<Route exact path="/login" component={LoginComponent}/>
</HashRouter>
Now let’s try an invalid hash route such as /#/invalid/
and see what happens.
Oops! 😕 Navigating to an invalid path renders an empty page without any components. So how can we fix this to show a component that display a 404 message?
Step 1 – Adding a path-less route
The first step to achieve our expected behavior is to add a path-less route that renders the 404 component. Then the new router configuration will look like below.
<HashRouter>
<Route exact path="/login" component={LoginComponent}/>
<Route component={My404Component}/>
</HashRouter>
Now if we reload our invalid path, we get our nice 404 page.
So we have achieved our goal, right? Just to be sure, let’s go back to our login page and see if it is already there.
Oh! Now we have our 404 component being rendered not only for the invalid paths but also with valid paths as well. Let’s see why.
When we add a route without a path, that route matches every path. Because of that, it will render its component with all the other paths in addition to that path specific components.
So what we have to do it to tell the React router that, it should only render this path, if only another matching path is not found.
Step 2 – Switching Routes
To achieve that, we can use the Switch
component provided with React Router within the Hash Router as below.
import {Switch} from "react-router-dom"
<HashRouter>
<Switch>
<Route exact path="/login" component={LoginComponent}/>
<Route component={Temp404Component}/>
</Switch>
</HashRouter>
When this Switch is used, it will render only the first matching route, so only the relevant component is rendered for valid routes and the 404 component will be rendered for all invalid routes.