20

My React routes are defined as follows:

...
<Route component={Header} />
<Route exact path="/" component={Landing} />
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
<Route component={Footer} />
...

I want to define a catch all route that catches anything that does not match the Landing, About or Contact routes, and instead redirects to a 404 Not found page. How can I do it with React Router 4?

James
  • 3,597
  • 11
  • 41
  • 76
  • 3
    use component https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/Switch.md – user93 Jul 21 '18 at 15:27

5 Answers5

17

Try this implementation

const AppRouter = (props) => {
        return (
            <BrowserRouter>
                <div>
                    <Header />
                    <Switch>
                        <Route exact path="/" component={Landing} />
                        <Route path="/about" component={About} />
                        <Route path="/contact" component={Contact} />
                        <Route component={NotFoundPage} />
                    </Switch>
                    <Footer />
                </div>
            </BrowserRouter>
        );
    }
nycynik
  • 7,371
  • 8
  • 62
  • 87
  • 6
    Two things: a) I thought this would render `NotFoundPage in all pages; and, b) You don't need `
    `twice, as it is in the code, I think.
    – Ed de Almeida Nov 17 '18 at 14:37
  • 1
    Within `Switch` only 1 match will ever be rendered. A `Route` without a `path` is always a match. Therefore, if nothing else matches, `NotFoundPage` will be rendered. Neither the `Header` nor `Footer` should be included within the `Switch` (i've submitted an edit to this answer to fix that part of the code) – Glenn 'devalias' Grant Jul 05 '21 at 02:16
  • A small note, Routes must be _direct_ children of ``, which is to say you cannot have your Routes in a fragment for example. – James B Oct 06 '21 at 20:22
  • Switch not supported in v6 – Benjamin Caure Aug 12 '22 at 15:29
16

Not sure if this will work for you as I have some 3rd party babel wrappers in use, but I get away with declaring all my routes then last putting

<Route path="/*" render={() => <SomeComponent /* possible prop injection */ />}/>

I've used this fairly frequently, but you can also use

<Route render={() => <SomeComponent />} />

I don't use this much as I prefer more landmarks in my code, but I got the above from https://tylermcginnis.com/react-router-handling-404-pages/

Jee Mok
  • 6,157
  • 8
  • 47
  • 80
Werlious
  • 583
  • 6
  • 15
  • 2
    bonus: `` can be `` – John Vandivier Jan 29 '21 at 15:44
  • Indeed it can! I only used `SomeComponent` because in most of my code, my 404 page is a custom component, and would rather render than than a wrapped redirect. But for simple/static 404 pages, `Redirect` does its job well – Werlious Feb 13 '21 at 07:17
2

React has a component called switch from 'react-router-dom'

So By wrapping your Routes inside of Switch, React Router will only render the first Route that matches. Meaning all other routes that don't match will be caught by specifying a route that doesn't have a attribute. See https://ui.dev/react-router-v4-handling-404-pages/

Phillip
  • 21
  • 1
  • For anyone wondering why this may not work, if you've declared your routes separately from the switch, this may be why. For example if you have a `const routes = <>... routes >` and try to do a `return ({routes})` it will not work as desired. – James B Oct 06 '21 at 20:19
0

Here's a one liner to redirect all other routes (placed after all other routes):

<Route path="/*" loader={() => redirect('/')} />
-2

Try this: <Route path="/" render={() => ( < SomeComponent /> / possible prop injection */ )} />

Here I'm catching all none existing routes end pushing it to a 404 component:

<Route path="/*" render={() => ( )} />

Remember

  • path = '/youreRoute' but also = {['/']} attributed
  • exact = exact match
Bill
  • 3,478
  • 23
  • 42