React-Router: ¿No se encuentra la ruta?

132

Considera lo siguiente:

var AppRoutes = [
    <Route handler={App} someProp="defaultProp">
        <Route path="/" handler={Page} />
    </Route>,

    <Route  handler={App} someProp="defaultProp">
        <Route path="/" handler={Header} >
            <Route path="/withheader" handler={Page} />
        </Route>
    </Route>,

    <Route handler={App} someProp="defaultProp">
        <Route path=":area" handler={Area} />
        <Route path=":area/:city" handler={Area} />
        <Route path=":area/:city/:locale" handler={Area} />
        <Route path=":area/:city/:locale/:type" handler={Area} />
    </Route>
];

Tengo una plantilla de aplicación, una plantilla de encabezado y un conjunto de rutas parametrizadas con el mismo controlador (dentro de la plantilla de aplicación). Quiero poder servir rutas 404 cuando no se encuentra algo. Por ejemplo, / CA / SanFrancisco debería ser encontrado y manejado por Area, mientras que / SanFranciscoz debería 404.

Así es como pruebo rápidamente las rutas.

['', '/', '/withheader', '/SanFranciscoz', '/ca', '/CA', '/CA/SanFrancisco', '/CA/SanFrancisco/LowerHaight', '/CA/SanFrancisco/LowerHaight/condo'].forEach(function(path){
    Router.run(AppRoutes, path, function(Handler, state){
        var output = React.renderToString(<Handler/>);
        console.log(output, '\n');
    });
});

El problema es / SanFranciscoz siempre está siendo manejado por la página de Área, pero quiero que sea 404. Además, si agrego un NotFoundRoute a la primera configuración de ruta, todas las páginas de Área 404.

<Route handler={App} someProp="defaultProp">
    <Route path="/" handler={Page} />
    <NotFoundRoute handler={NotFound} />
</Route>,

¿Qué estoy haciendo mal?

Aquí hay una esencia que se puede descargar y experimentar.

https://gist.github.com/adjavaherian/aa48e78279acddc25315

4m1r
fuente
Para referencia futura para las personas que terminan con esta pregunta, además de la respuesta correcta a continuación, lea este artículo . Lo encontré antes y creo que esa persona lo explica perfectamente.
Dimitris Damilos

Respuestas:

248

DefaultRoute y NotFoundRoute se eliminaron en react-router 1.0.0.

Me gustaría enfatizar que la ruta predeterminada con el asterisco debe ser la última en el nivel de jerarquía actual para que funcione. De lo contrario, anulará todas las demás rutas que aparecen después en el árbol porque es la primera y coincide con cada ruta.

Para react-router 1, 2 y 3

Si desea mostrar un 404 y mantener la ruta (la misma funcionalidad que NotFoundRoute)

<Route path='*' exact={true} component={My404Component} />

Si desea mostrar una página 404 pero cambiar la url (la misma funcionalidad que DefaultRoute)

<Route path='/404' component={My404Component} />
<Redirect from='*' to='/404' />

Ejemplo con múltiples niveles:

<Route path='/' component={Layout} />
    <IndexRoute component={MyComponent} />
    <Route path='/users' component={MyComponent}>
        <Route path='user/:id' component={MyComponent} />
        <Route path='*' component={UsersNotFound} />
    </Route>
    <Route path='/settings' component={MyComponent} />
    <Route path='*' exact={true} component={GenericNotFound} />
</Route>

Para react-router 4 y 5

Mantener el camino

<Switch>
    <Route exact path="/users" component={MyComponent} />
    <Route component={GenericNotFound} />
</Switch>

Redireccionar a otra ruta (cambiar url)

<Switch>
    <Route path="/users" component={MyComponent} />
    <Route path="/404" component={GenericNotFound} />
    <Redirect to="/404" />
</Switch>

¡El orden importa!

Janne Annala
fuente
si tienes una aplicación redux, ¿cómo lo haces ?: <Redirect from='*' to='/home' />en esta sintaxis:const routes = { component: Main, childRoutes: [ { path: '/', component: Home }, ], indexRoute: { component: Main, }, };
tatsu
1
si desea establecer accesorios para el 404-Compontent use este código:<Route render={(props)=> <MyComponent myProp={someVar} {...props} />} />
Marco Weber
¿Qué tal una página 500? Como una página que se supone que se carga pero la API da un error. ¿Cómo mostrar esto en lugar de la página que falló al mantener la ruta?
PixMach
<Redirect to = "/ 404" /> provoca que la profundidad máxima de actualización exceda en react-router-dom 5.0.0. Incluso si la página 404 sale, se redirige.
MiguelSlv
44
No me gusta usar una redirección porque oculta la URL problemática del usuario. También requiere presionar dos veces para volver a la página anterior.
sdgfsdh
39

En las versiones más recientes de react-router, desea ajustar las rutas en un Switch que solo representa el primer componente coincidente. De lo contrario, vería múltiples componentes renderizados.

Por ejemplo:

import React from 'react';
import ReactDOM from 'react-dom';
import {
  BrowserRouter as Router,
  Route,
  browserHistory,
  Switch
} from 'react-router-dom';

import App from './app/App';
import Welcome from './app/Welcome';
import NotFound from './app/NotFound';

const Root = () => (
  <Router history={browserHistory}>
    <Switch>
      <Route exact path="/" component={App}/>
      <Route path="/welcome" component={Welcome}/>
      <Route component={NotFound}/>
    </Switch>
  </Router>
);

ReactDOM.render(
  <Root/>,
  document.getElementById('root')
);
metakermit
fuente
12
No es necesario incluir path="*"en la ruta NotFound. Omitir pathhará que la ruta coincida siempre.
chipit24
1
Para las personas que llegan tarde, @ chipit24 es correcto, para evitar confusiones simplemente omita pathpor completo las rutas desconocidas
Altair312
14

Con la nueva versión de React Router (usando 2.0.1 ahora), puede usar un asterisco como ruta para enrutar todas las 'otras rutas'.

Entonces se vería así:

<Route route="/" component={App}>
    <Route path=":area" component={Area}>
        <Route path=":city" component={City} />
        <Route path=":more-stuff" component={MoreStuff} />    
    </Route>
    <Route path="*" component={NotFoundRoute} />
</Route>
dejakob
fuente
10

Esta respuesta es para react-router-4. Puede ajustar todas las rutas en el bloque Switch, que funciona igual que la expresión de mayúsculas y minúsculas, y representa el componente con la primera ruta coincidente. p.ej)

<Switch>
      <Route path="/" component={home}/>
      <Route path="/home" component={home}/>
      <Route component={GenericNotFound}/> {/* The Default not found component */}
</Switch>

Cuándo usar exact

Sin exacto:

<Route path='/home'
       component = {Home} />

{/* This will also work for cases like https://<domain>/home/anyvalue. */}

Con exacto:

<Route exact path='/home'
       component = {Home} />

{/* 
     This will NOT work for cases like https://<domain>/home/anyvalue. 
     Only for https://<url>/home and https://<domain>/home/
*/}

Ahora, si acepta parámetros de enrutamiento y resulta incorrecto, puede manejarlo en el componente de destino. p.ej)

<Route exact path='/user/:email'
       render = { (props) => <ProfilePage {...props} user={this.state.user} />} />

Ahora en ProfilePage.js

if(this.props.match.params.email != desiredValue)
{
   <Redirect to="/notFound" component = {GenericNotFound}/>
   //Or you can show some other component here itself.
}

Para obtener más detalles, puede consultar este código:

App.js

ProfilePage.js

Pransh Tiwari
fuente
6

De acuerdo con la documentación , se encontró la ruta , aunque el recurso no.

Nota : Esto no está destinado a usarse cuando no se encuentra un recurso. Existe una diferencia entre el enrutador que no encuentra una ruta coincidente y una URL válida que da como resultado que no se encuentre un recurso. El url course / 123 es un url válido y da como resultado una ruta coincidente, por lo tanto, se "encontró" en lo que respecta al enrutamiento. Luego, si buscamos algunos datos y descubrimos que el curso 123 no existe, no queremos hacer la transición a una nueva ruta. Al igual que en el servidor, continúa y sirve la url, pero presenta una interfaz de usuario diferente (y usa un código de estado diferente). Nunca debe intentar hacer la transición a un NotFoundRoute.

Por lo tanto, siempre puede agregar una línea Router.run()antes React.render()para verificar si el recurso es válido. Simplemente pase un accesorio al componente o anule el Handlercomponente con uno personalizado para mostrar la vista NotFound.

Brad B
fuente
gracias @brad, tienes razón, usted tiene que manejar esto con el componente y, o sustituir el controlador antes de router.run
4m1r
3
NotFound fue desaprobado github.com/reactjs/react-router/releases/tag/v1.0.0 , ahora uso <Route path="*" to="/dest" />o <Redirect from="*" to="/dest" />como la última sub ruta para que coincida, creo
ptim
5

Acabo de echar un vistazo rápido a su ejemplo, pero si lo entendí de la manera correcta, está tratando de agregar rutas 404 a segmentos dinámicos. Tuve el mismo problema hace un par de días, encontré # 458 y # 1103 y terminé con un cheque hecho a mano dentro de la función de renderizado:

if (!place) return <NotFound />;

¡Espero que ayude!

Jörn
fuente
gracias @jorn, creo que tienes razón, esto parece solo direccionable desde el nivel de componente
4m1r