React-router: Showing NotFound route when resource is not found

Created on 6 Oct 2014  路  5Comments  路  Source: ReactTraining/react-router

I would like to use a global 404 page for any unmatched paths, but I am having trouble with route handlers that need to check for existence of some resource:

<Route path=":id" handler={ResourcePage}>
  ...
</Route>

<NotFoundRoute name="notFound" handler={ErrorNotFoundPage} />

In the above example the ResourcePage is going to asynchronously check for resource existence. If the identifier in the matched path does not correspond to a resource I would like to show the ErrorNotFoundPage but not change the URL.

However, I have failed to find a satisfying solution. If i abort the transition in a transition hook, the user is redirected to the previous route, and if I this.transitionTo('notFound') using the Transition mixin, an error is thrown due to a needed splat parameter which, when given, results in a URL change.

Is it somehow possible to force path matching to fail for a Route in a transition hook so it can continue down to the NotFoundRoute, or perhaps transition to another route without changing the URL?

Most helpful comment

Looks like the same issue as this bug. There needs to be a way to abort a route even if it matches. That way the router can continue to the 404 route and we can detect this on the server to respond with a 404 error code.

All 5 comments

You don't have to change routes to render the same thing in two places, just reuse a view.

var ResourcePage = React.createClass({
  render: function() {
    if (this.state.didNotFindAnything) {
      return <NotFoundView />
    }
    // ...
  }
});

var NotFoundRoute = React.createClass({
  render: function() {
    return <NotFoundView />
  }
});

<Route handler={ResourcePage}/>
<NotFoundRoute handler={NotFoundRoute}/>

Perhaps I simplified my problem too much. Some of our resource routes are nested inside other routes, and our current solution is similar to what you suggest, except we use separate NotFoundViews for different sub-resources (since our global 404 handler looks strange inside some of the parent routes).

This works, but we would prefer to consistently display the same 404 page for missing resources as well as top-level route handlers.

Would it make sense to, in the transition hooks, add a method to the transition object similar to abort() that, instead of completely cancelling the transition, instead continues path matching but skipping that route?

Looks like the same issue as this bug. There needs to be a way to abort a route even if it matches. That way the router can continue to the 404 route and we can detect this on the server to respond with a 404 error code.

+1
The only workaround I see here is to use some kind of 404 flag in some Flux store and reset it every time a router.run callback is called.
But I think router should provide an easier way for such a common case.

+1

This means I'm going to have to add boilerplate to all of my major routes that basically does what @ryanflorence describes above. It isn't a ton of code but it'd be awesome if I could just call this.notFound() or something and it would maintain the URL but route to the nearest <NotFoundRoute /> handler.

mixins: [Navigation],
componentDidMount: function() {
  fetch(this.onDataResponse);
},
onDataResponse: function(response) {
  if (response === 'not found') {
    this.notFound();
  }
},

Instead of having to make all of my major routes aware of my <NotFoundView />, only ReactRouter has to know about it and my major routes can pass handling back to ReactRouter to find the NotFound route.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tomatau picture tomatau  路  3Comments

maier-stefan picture maier-stefan  路  3Comments

imWildCat picture imWildCat  路  3Comments

ryansobol picture ryansobol  路  3Comments

Waquo picture Waquo  路  3Comments