React-Router: rota não encontrada?

132

Considere o seguinte:

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>
];

Eu tenho um modelo de aplicativo, um cabeçalho de modelo e um conjunto de rotas parametrizado com o mesmo manipulador (no modelo de aplicativo). Quero poder servir rotas 404 quando algo não for encontrado. Por exemplo, / CA / SanFrancisco deve ser encontrado e tratado por Área, enquanto / SanFranciscoz deve 404.

Veja como teste rapidamente as rotas.

['', '/', '/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');
    });
});

O problema é que / SanFranciscoz está sempre sendo tratado pela página Área, mas quero que seja 404. Além disso, se eu adicionar um NotFoundRoute à primeira configuração de rota, todas as páginas Área 404.

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

O que estou fazendo de errado?

Aqui está uma essência que pode ser baixada e testada.

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

4m1r
fonte
Para referência futura para pessoas que acabam com essa pergunta, além da resposta correta abaixo, leia este artigo . Me deparei com isso mais cedo e acho que essa pessoa explica perfeitamente.
Dimitris Damilos

Respostas:

248

DefaultRoute e NotFoundRoute foram removidos no react-router 1.0.0.

Gostaria de enfatizar que a rota padrão com o asterisco deve ser a última no nível atual da hierarquia para funcionar. Caso contrário, ele substituirá todas as outras rotas que aparecerem depois na árvore porque é a primeira e corresponde a todos os caminhos.

Para o roteador de reação 1, 2 e 3

Se você deseja exibir um 404 e manter o caminho (mesma funcionalidade que NotFoundRoute)

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

Se você deseja exibir uma página 404, mas alterar o URL (mesma funcionalidade do DefaultRoute)

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

Exemplo com vários níveis:

<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 o roteador de reação 4 e 5

Mantenha o caminho

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

Redirecionar para outra rota (alterar URL)

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

A ordem é importante!

Janne Annala
fonte
se você tem um aplicativo redux, como você faz: <Redirect from='*' to='/home' />nesta sintaxe:const routes = { component: Main, childRoutes: [ { path: '/', component: Home }, ], indexRoute: { component: Main, }, };
tatsu 13/09/17
1
se você deseja definir adereços para o 404-Compontent, use este código:<Route render={(props)=> <MyComponent myProp={someVar} {...props} />} />
Marco Weber
Que tal uma página de 500? Como uma página que deveria carregar, mas a API apresenta um erro. Como mostrar isso em vez da página que falhou ao manter a rota?
PixMach
<Redirecionar para = "/ 404" /> faz com que a profundidade máxima de atualização exceda no react-router-dom 5.0.0. Mesmo se a página 404 sair, ela será redirecionada.
MiguelSlv
4
Não gosto de usar um redirecionamento porque oculta a URL problemática do usuário. Também é necessário retornar duas vezes para retornar à página anterior.
sdgfsdh
39

Nas versões mais recentes do react-router, você deseja agrupar as rotas em um Switch que renderiza apenas o primeiro componente correspondente. Caso contrário, você verá vários componentes renderizados.

Por exemplo:

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
fonte
12
Você não precisa incluir path="*"na rota NotFound. A omissão pathfará com que a rota corresponda sempre.
chipit24
1
Para as pessoas que chegam atrasadas, @ chipit24 está certo, para evitar confusão, basta omitir as pathrotas totalmente desconhecidas
Altair312
14

Com a nova versão do React Router (usando o 2.0.1 agora), você pode usar um asterisco como um caminho para rotear todos os 'outros caminhos'.

Então ficaria assim:

<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
fonte
10

Esta resposta é para react-router-4. Você pode agrupar todas as rotas no bloco Switch, que funciona exatamente como a expressão de maiúsculas e minúsculas, e renderiza o componente com a primeira rota correspondente. por exemplo)

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

Quando usar exact

Sem exata:

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

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

Com exato:

<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/
*/}

Agora, se você estiver aceitando parâmetros de roteamento e se estiver incorreto, poderá tratá-lo no próprio componente de destino. por exemplo)

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

Agora no ProfilePage.js

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

Para mais detalhes, você pode passar por este código:

App.js

ProfilePage.js

Pransh Tiwari
fonte
6

De acordo com a documentação , a rota foi encontrada, embora o recurso não fosse.

Nota : Não se destina a ser usado quando um recurso não for encontrado. Há uma diferença entre o roteador não encontrar um caminho correspondente e um URL válido que resulta em um recurso não encontrado. O curso de URL / 123 é um URL válido e resulta em uma rota correspondente; portanto, foi "encontrado" no que diz respeito ao roteamento. Então, se buscarmos alguns dados e descobrirmos que o curso 123 não existe, não queremos fazer a transição para uma nova rota. Assim como no servidor, você segue em frente e serve o URL, mas renderiza uma interface do usuário diferente (e usa um código de status diferente). Você nunca deve tentar fazer a transição para um NotFoundRoute.

Portanto, você sempre pode adicionar uma linha Router.run()antes React.render()para verificar se o recurso é válido. Basta passar um suporte para o componente ou substituir o Handlercomponente por um personalizado para exibir a visualização NotFound.

Brad B
fonte
graças @ Brad, você está certo, você tem que lidar com isso com o componente e ou substituir o manipulador antes router.run
4m1r
3
NotFound foi descontinuado github.com/reactjs/react-router/releases/tag/v1.0.0 , agora use <Route path="*" to="/dest" />ou <Redirect from="*" to="/dest" />como a última sub rota para corresponder, acredito
ptim
5

Acabei de dar uma olhada rápida no seu exemplo, mas se entendi da maneira certa, você está tentando adicionar 404 rotas a segmentos dinâmicos. Eu tive o mesmo problema há alguns dias, encontrei os números 458 e 1103 e acabei com uma verificação feita manualmente na função de renderização:

if (!place) return <NotFound />;

espero que ajude!

Jörn
fonte
graças @jorn, eu acho que você está certo, isso parece ser apenas endereçável a partir do nível de componente
4m1r