Gershon Papi
Gershon Papi

Reputation: 5106

Error handling in react router server-side

I'm developing isomorphic app with react-router & express. I'm using react router in server side rendering. I want to have custom error pages, that will be sent upon either server-side error, rendering error or ofcourse- not found. But I'm having problems connecting the dots. Here are my routes:

<Route component={Index} path="/">
  <IndexRoute component={Home} />
  <Route component={Chart} path="chart" />
  <Route component={Login} path="login" />
  <Route component={Error} path="error" /> //path="*" takes care only for not found,
                                             and it still sends the client a 200 status code
</Route>

And here is my only express route:

app.use((req, res, next) => {
  const location = createLocation(req.url);
  const css = [];
  match({ routes, location }, (err, redirectLocation, renderProps) => {
    if (err) {
      //500 internal error
      return next(err);
    }
    if(redirectLocation){
      //react-router redirect, no problems here
      return res.redirect(redirectLocation.path + redirectLocation.query);
    }
    if (!renderProps){
      //404 not found
      let error = new Error();
      error.message = "Not Found";
      error.status = 404;
      return next(err);
    }

    res.status(200).end(getHtml(renderProps));
  }
}

//...
//some regular express error handler to log in console and (as of right now) send simple text to client.

while getHtml(renderProps) generates html with react's renderToString() on <RouterContext {...renderProps} />.

I want to somehow route to the error component, which will have access to the error code using the router context (or some other way) so it will show an appropiate error.

Any ideas?

Upvotes: 1

Views: 3414

Answers (2)

Stefano Pastore
Stefano Pastore

Reputation: 26

I find this solution for 404 state on server-side render,

configure routes like this:

<Route component={Index} path="/">
  <IndexRoute component={Home} />
  <Route component={Chart} path="chart" />
  <Route component={Login} path="login" />
  <Route component={Error} path="*" notFound />
</Route>

And set express route like this:

app.use((req, res, next) => {
  const location = createLocation(req.url);
  const css = [];
  match({ routes, location }, (err, redirectLocation, renderProps) => {
    if (err) {
      //500 internal error
      return next(err);
    }
    if(redirectLocation){
      //react-router redirect, no problems here
      return res.redirect(redirectLocation.path + redirectLocation.query);
    }
    if (!renderProps){
      //404 not found
      let error = new Error();
      error.message = "Not Found";
      error.status = 404;
      return next(err);
    }

    const notFound = renderProps.routes.filter((route) => route.notFound).length > 0;
    res.status(notFound ? 404 : 200);

    res.end(getHtml(renderProps));
  }
}

Upvotes: 1

user1736525
user1736525

Reputation: 1129

I could be wrong, but give this a try:

if (!renderProps) {
  //404 not found
  let error = new Error();
  error.message = "Not Found";
  error.status = 404;
  res.status(error.status).end(someErrorHtml); // <- I think you are missing this
  return next(err);
}

Upvotes: 0

Related Questions