How to let react router respond with 404 status code?

Viewed 47921

I'm using react router as root and all requests under "/" are directed to react router. And when react router found that the url is not matched with any of the defined components, it renders with NoMatch component. And here goes the problem, NoMatch is rendered and that's what I want, but the status code is still 200 instead of 404. And when my css or js files are placed with a wrong url react router does the same thing, it responds with 200! And then the page tells me that there's some problem with my resources content type!

So, how can I use react router to handle everything in the "/" and still get it to treat 404 errors right(to respond with 404 status code)?

code in react router

render((
  <Router history={browserHistory}>
    <Route path="/" component={App}>
      <IndexRoute component={Index}/>
      <Route path="archived" component={App}>
        <IndexRoute component={ArchivedPage}/>
        <Route path="project/:projectId" component={ArchivedDetailPage}/>
      </Route>
      <Route path="*" component={NoMatch}/>
    </Route>
  </Router>
), document.getElementById('app'));

the servre side

  router.use('/', function(req, res, next) {
    res.render('index-react', {
      title: 'some title'
    });
  });
4 Answers

I did some digging, this is how we do things in the v4 release.

<Route
  render={({ staticContext }) => {
    if (staticContext) {
      staticContext.statusCode = 404
    }
    return <NotFound />
  }}
/>

The Route component is used to access the staticContext which has a statusCode prop that you can set if you use the StaticRouter component to render on the server.

Server code looks something like this (with some TypeScript typing)

const currentLocation: Location = {
  pathname: req.pathname,
  search: req.search,
  hash: '',
  state: undefined
}

const staticRouterContext: StaticContext & StaticRouterContext = {}

ReactDOMServer.renderToString(
  <StaticRouter location={currentLocation} context={staticRouterContext}>
  ...
  </StaticRouter>
)

if (staticRouterContext.statusCode) {
  res.status(staticRouterContext.statusCode)
}

Note: I think the typings are a bit wonky because the StaticRouterContext doesn't have the statusCode prop from the StaticContext interface. Probably a mistake in the typings. This works just fine though.

Related