Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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'
    });
  });
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
382 views
Welcome To Ask or Share your Answers For Others

1 Answer

With react-router 2.0.0 you can do:

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

EDIT:

What you would need to do, is to create a custom attribute on your route definition, like you can see above (status).

When you are about rendering you component on server side, check on this attribute and send a response with a the code of this attribute:

routes.js

import React from 'react';
import {IndexRoute, Route} from 'react-router';

import {
    App,
    Home,
    Post,
    NotFound,
} from 'containerComponents';

export default () => {
    return (
    <Route path="/" component={App}>

        <IndexRoute component={Home} />
        <Route path='post/' component={Post} />

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

    </Route>
  );
};

server.js:

import { match } from 'react-router';
import getRoutes from './routes';
....
app.use((req, res) => {
match({ history, routes: getRoutes(), location: req.originalUrl }, (error, 
        redirectLocation, renderProps) => {
        if (redirectLocation) {
          res.redirect(redirectLocation.pathname + redirectLocation.search);
        } else if (error) {
          console.error('ROUTER ERROR:', error);
          res.status(500);
        } else if (renderProps) {

            const is404 = renderProps.routes.find(r => r.status === 404) !== undefined;
        }
        if (is404) {
          res.status(404).send('Not found');
        } else {
            //Go on and render the freaking component...
        }
    });
});

Sorry about that... certainly my solution wasn't working by itself, and I missed the proper piece of code where you actually check on this attribute and render accordingly.

As you can see, I just send the 'Not found' text to the client, however, it would be best if you catch the component to render from renderProps (NoMatch in this case) and render it.

Cheers


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...