3

I've been building out this application for a little while now and figured it was probably time to add a 404 page to my index.js (I probably should have done this first, so shame on me). The issue is that I can't seem to get the 404 page to render when a route is not matched, instead it's just displaying a blank page. I've looked online but there aren't many examples out there using a 404 page with nested routing like I have here in my index.js file:

ReactDOM.render((
    <BrowserRouter>
        <Switch>

            <Route path='/customer'>
                <CustomerPortal>
                    <Route exact path='/customer' component={CustomerPortalHome} />
                    <Route path='/customer/quote/:info?' component={CustomerQuote} />
                    <Route path='/customer/direct_quote/:ref?' component={Referral} />
                    <Route path='/customer/ad/:info?' component={Ad} />
                </CustomerPortal>
            </Route>
            
            <Route path='/pay'>
                <CustomerPortal>
                    <Route exact path='/pay' component={PaymentPortal} />
                    <Route path='/pay/:txn' component={PaymentPage} />
                </CustomerPortal>
            </Route>

            <Route exact path="/login" component={Login} />

            <Route path='/'>
                <Auth>
                    <App>
                        <Route exact path='/' component={Dashboard} />
                        <Route path='/stores' component={Stores} />
                        <Route path='/archives' component={Archives} />
                        <Route path='/users' component={Users} />
                        <Route path='/contracts' component={Contracts} />
                        <Route path='/graphics' component={Graphics} />
                        <Route exact path='/submit_contract' component={MyContracts} />
                        <Route path='/submit_contract/new' component={ContractForm} />
                        <Route path='/submit_contract/renewal/:id' component={ContractForm} />
                    </App>
                </Auth>
            </Route>

            <Route component={NotFound} />
        </Switch>
    </BrowserRouter>), document.getElementById('appRoot'));

My application has a customer side and an admin side hence the multiple different routes. I've tried to move my NotFound component in many different places but I still don't get the result I'm looking for. Keeping it where it is now, if I tried to go to the route /someroute it will just display a blank page. If I move my NotFound component inside the App component at the bottom, this will display 404 on all of my other pages which is also not what I want to happen. The problem with having nested routes is that even if I were to go to anything that matches the home route / then it will display in there so I don't think having it at the end of the switch makes sense, but maybe I'm wrong. If anyone has any ideas or suggestions on how I could make this work for all routes that would be great. TIA!

EDIT

I was able to figure this out on my own by some brute force trial and error, along with some more research. I was able to solve this issue by adding nested Switch components to each one of my main routes, and then put my NotFound component at the bottom of each main route like so.

ReactDOM.render((
    <BrowserRouter>
        <Switch>

            <Route path='/customer'>
                <CustomerPortal>
                  <Switch>
                    <Route exact path='/customer' component={CustomerPortalHome} />
                    <Route path='/customer/quote/:info?' component={CustomerQuote} />
                    <Route path='/customer/direct_quote/:ref?' component={Referral} />
                    <Route path='/customer/ad/:info?' component={Ad} />
                    <Route component={NotFound} />
                   </Switch>
                </CustomerPortal>
            </Route>
            
            <Route path='/pay'>
                <CustomerPortal>
                  <Switch>
                    <Route exact path='/pay' component={PaymentPortal} />
                    <Route path='/pay/:txn' component={PaymentPage} />
                    <Route component={NotFound} />
                  </Switch>
                </CustomerPortal>
            </Route>

            <Route exact path="/login" component={Login} />

            <Route path='/'>
                <Auth>
                    <App>
                      <Switch>
                        <Route exact path='/' component={Dashboard} />
                        <Route exact path='/stores' component={Stores} />
                        <Route exact path='/archives' component={Archives} />
                        <Route exact path='/users' component={Users} />
                        <Route exact path='/contracts' component={Contracts} />
                        <Route exact path='/graphics' component={Graphics} />
                        <Route exact path='/submit_contract' component={MyContracts} />
                        <Route path='/submit_contract/new' component={ContractForm} />
                        <Route path='/submit_contract/renewal/:id' component={ContractForm} />
                        <Route component={NotFound} />
                      </Switch>
                    </App>
                </Auth>
            </Route>

            <Route component={NotFound} />
        </Switch>
    </BrowserRouter>), document.getElementById('appRoot'));

I also added exact paths for all paths that weren't dynamic. Hopefully this helps somebody.

Michael
  • 1,454
  • 3
  • 19
  • 45
  • This seems like a task best suited for an .htaccess file. – jcklopp Dec 30 '20 at 16:50
  • @jcklopp I don't know what that is so I guess I will take a look, thanks. – Michael Dec 30 '20 at 18:51
  • Its pretty straight forward. Create a file named .htaccess in your root web directory with a directive on how to handle a http 404 errors. If you need a place to start you can try this link: https://stackoverflow.com/questions/19962787/rewrite-url-after-redirecting-404-error-htaccess – jcklopp Dec 31 '20 at 03:40

3 Answers3

0

Problem is it goes inside

<Route path='/'>

because exact keyword is not there, hence it matches'/something' with '/'.

If I try guessing about your Auth component, then first simple solution from my side to you would be something like below

<Route path='/'>
                <Auth>
                    <App>
                       ...
                    </App>

<Route component={NotFound} />
                </Auth>
    <Route component={NotFound} />
            </Route>
    <Route component={NotFound} />
    ```

Vaibhav Arora
  • 94
  • 1
  • 9
0

From what I can observe in your codes. You will need to add the Router with the NotFound component as child in the nested routers since your parent routers does not contain the exact property.

Samuel
  • 13
  • 4
0

You can use what you have, but change the route to path="*". This will make it so anything that is not a defined path goes to the 404 page.

<Route path="*" component={PageNotFound} />

There is a tutorial here: https://naveenda.medium.com/creating-a-custom-404-notfound-page-with-react-routers-56af9ad67807

ryguy8806
  • 93
  • 7
  • This gives me the same issue where the page shows up blank and doesn't render the ```NotFound``` component. – Michael Dec 30 '20 at 18:55