6

I have a react-router 3.0.0 setup with a NotFound component I'm showing as a fallback:

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

However this returns a redirect and the google crawler is complaining about soft 404s. Can I both redirect to my NotFound component and send a 404, similar to what Github does for instance? I've tried the following suggestion from here: How to let react router respond with 404 status code?

<Route component={NotFound} path="*" status={404}/>

But that just gives me a 404 without displaying the component.

How can the above be accomplished?

paqash
  • 2,142
  • 1
  • 15
  • 22
  • 2
    If you want to return a HTTP 404 status, you'll need to do this from the server. You can use `match` for this. If the match fails you can return a 404 status in the response. http://knowbody.github.io/react-router-docs/api/match.html – cheersjosh Feb 15 '17 at 01:20
  • 1
    Check out the other response in that same question you linked. http://stackoverflow.com/a/36075450/2030321 Taion is actually one of the developers behind [tag:react-router] (and some other libraries too). Pretty much also what @cheersjosh said. It must happen from the server too. – Chris Feb 15 '17 at 08:18
  • Ok, thanks. I'm not doing server-side rendering though, and was hoping there might be a quick solution like the one I tried. – paqash Feb 15 '17 at 09:09

1 Answers1

0

Just to close the loop on this - I didn't want to go the server-side rendering route, so I implemented the following in my global error handler middleware:

     if (err.name === 'UnauthorizedError') {
        res.status(401).send(prepareErrorResponse(isXhr, 'Acess Denied'));
      } else if (err.status === 404) {
       res.status(404).send(prepareErrorResponse(isXhr, 'Not Found'));
       if (req.accepts('html')) {
         // Respond with html page.
         fs.readFile(__dirname + '/../404.html'), 'utf-8', function(err, page) {
           res.writeHead(404, {'Content-Type': 'text/html'});
           res.write(page);
           res.end();
         });
       } else {
         if (req.accepts('json')) {
           // Respond with json.
           res.status(404).send({ error: 'Not found' });
         } else {
           // Default to plain-text. send()
           res.status(404).type('txt').send('Not found');
         }
       }
     }

Basically instead of showing a NotFound component on the client (with a soft 404), I'm serving a NotFound page directly from the server (with a 404 status).

paqash
  • 2,142
  • 1
  • 15
  • 22
  • How do you get this `err.status === 404` without rendering on the server? – Alexis Wilke Feb 16 '19 at 22:22
  • This is server code, the server is express I have a express router catch all that sets the err.status and calls the above code – paqash Feb 18 '19 at 08:22
  • `router.use((req, res, next) => { var err = new Error('Not Found'); err.status = 404; next(err); });` – paqash Feb 18 '19 at 08:22