web-dev-qa-db-fra.com

Comment laisser le routeur réagir avec le code d'état 404?

J'utilise le routeur de réaction en tant que root et toutes les demandes sous "/" sont dirigées vers le routeur de réaction. Et lorsque le routeur de réaction a constaté que l'URL ne correspond à aucun des composants définis, il s'affiche avec le composant NoMatch. Et voilà le problème, NoMatch est rendu et c'est ce que je veux, mais le code d'état est toujours 200 au lieu de 404. Et lorsque mes fichiers css ou js sont placés avec une mauvaise URL, le routeur réagit de la même manière, il répond avec ! Et puis la page me dit qu'il y a un problème avec le type de contenu de mes ressources!

Alors, comment puis-je utiliser le routeur de réaction pour tout gérer dans le "/" tout en le faisant traiter les erreurs 404 correctement (pour répondre avec le code d'état 404)?

code dans le routeur de réaction

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'));

le côté servre

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

Avec react-router 2.0.0, vous pouvez faire:

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

MODIFIER:

Ce que vous devez faire est de créer un attribut personnalisé dans la définition de votre itinéraire, comme vous pouvez le voir ci-dessus (statut).

Lorsque vous voulez rendre votre composant côté serveur, vérifiez cet attribut et envoyez une réponse avec le code de cet attribut:

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...
        }
    });
});

Désolé, ma solution ne fonctionnait pas d'elle-même, et j'ai manqué le code qui permet de vérifier cet attribut et de l'afficher en conséquence.

Comme vous pouvez le constater, j'envoie simplement le texte "Non trouvé" au client. Toutefois, il serait préférable de capturer le composant à rendre à renderProps (NoMatch dans ce cas) et de le restituer.

À votre santé

13
rmartrenado

Zen: Quel est le code d'erreur d'un réseau silencieux?

Je suis aussi perplexe sur cette question. Les cas étranges, vous ne modifiez pas le code d'erreur HTTP. Nous pensons que nous devrions, car une URL aléatoire a été appelée, mais pourquoi?

Dans un SPA (application à une seule page), il n’ya pas de trafic réseau, mais seulement un changement de volet. Le code d'erreur HTTP est dans les en-têtes pour servir une nouvelle page, alors que tout le contenu est dans un <div> nommé qui ne recharge pas une nouvelle page Il faudrait jeter la page, transmettre et afficher une nouvelle page pour obtenir le code retour 404, puis renvoyer la page d'origine lorsque l'utilisateur s'éloigne.

Et, ce n'est que l'utilisateur. Le code d'erreur 404, ou tout autre code HTTP, est vraiment un indice pour le navigateur ou le service. Si le demandeur est un navigateur, l’être humain reçoit une meilleure indication que ce que le navigateur pourrait fournir. Si le demandeur est un robot, il recherche probablement 404 dans <h1>. Si le demandeur utilise votre site Web en tant qu'API, pourquoi est-ce une bonne chose?

La réponse est donc que nous définissons les codes de statut HTTP par habitude. Ne pas.

6
Charles Merriam

Pour ce faire, vous devez également exécuter la correspondance sur le serveur pour voir si un itinéraire correspond. Bien entendu, si vous envisagez de le faire, vous pouvez également effectuer un rendu complet côté serveur! Consultez le guide de rendu server .

3
taion

J'ai fait quelques recherches, voici comment nous procédons dans la version v4.

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

Le composant Route est utilisé pour accéder à staticContext qui a un prop statusCode que vous pouvez définir si vous utilisez le composant StaticRouter pour restituer sur le serveur.

Le code serveur ressemble à quelque chose comme ceci (avec du typage TypeScript)

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: Je pense que les saisies sont un peu insignifiantes parce que StaticRouterContext n'a pas le prop statusCode de l'interface StaticContext. Probablement une erreur dans les typages. Cela fonctionne très bien cependant.

1
John Leidegren