Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Como redirecionar para uma página 404 ao utilizar os Context Providers?

No curso de React Router, aprendemos que o código:

return (
    <Router>
      <Cabecalho />
      <Switch>
        <Route exact path='/'>
          <Home />
        </Route>
        <Route path='/sobre'>
          <Sobre />
        </Route>

        <Route>
          <Pagina404 />
        </Route>

      </Switch>
    </Router>

vai redirecionar todas as rotas não especificadas para a última Route (que leva à página 404). Porém ao tentar utilizar isso com os context providers eu não consigo essa mesma funcionalidade:

  • A página 404 é sempre exibida logo após qualquer renderização de rota (quando a rota da Page404 é colocada depois do switch - nesse caso até entendo ela ser renderizada - ou dentro dos contextos)

Insira aqui a descrição dessa imagem para ajudar na acessibilidadeou então:

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

//...
      </Switch>
      <Route>
        <Page404 />
      </Route>
    </BrowserRouter>);}

//ou

//...
            <Route path="/carrinho">
                <Carrinho />
              </Route>
              <Route>
                <Page404 />
              </Route>
            </PagamentoProvider>
          </CarrinhoProvider>
        </UsuarioProvider>
      </Switch>
    </BrowserRouter> );}

//ou

//...
          </CarrinhoProvider>
              <Route>
                <Page404 />
              </Route>
        </UsuarioProvider>
      </Switch>
    </BrowserRouter> );}
  • Ou a Page 404 nunca é renderizada (se colocada entre o fechamento do último contexto e o fechamento do Switch)
//...
            </PagamentoProvider>
          </CarrinhoProvider>
        </UsuarioProvider>
              <Route>
                <Page404 />
              </Route>
      </Switch>
    </BrowserRouter>  );}

Então como utilizar os Contextos nessas situações? Ou como redirecionar as rotas que não dependem de contexto, como a Page404)?

É ok eu englobar o switch em todos os contextos? (nesse caso funciona, mas me parece um pouco sem sentido, já que todas as rotas têm acesso a todos os contextos)

2 respostas
solução!

Fala Tiago, bom dia, tudo certo??

Sua pergunta é bem interessante! Vou te explicar primeiro o porquê do problema e depois duas formas de resolvê-lo, beleza?

O problema: Caso você deixe a rota de 404 dentro do Switch, o problema no caso é que o <Switch> está reconhecendo o component Provider como uma rota, então ele não chega a rota de 404. Caso você deixe ele fora do Switch, o Router não "para de ler" na primeira rota encontrada, ou seja, ele encontra uma rota dentro do <Switch> e depois coloca a sua rota 404 como se fosse um componente padrão que sempre deve aparecer como um <Footer> por exemplo.

Para solucionarmos isso temos duas alternativas, ou Colocar o Provider dentro do Route ou criar outro Switch dentro das rotas.

Colocando o Provider dentro dos Routes:

<BrowserRouter>
  <UsuarioProvider>
    <Switch>
      <Route exact path="/">
        <Login />
      </Route>
      <Route path="/feira">
        <PagamentoProvider>
          <CarrinhoProvider>
            <Feira />
          </CarrinhoProvider>
        </PagamentoProvider>
      </Route>
      <Route path="/carrinho">
        <PagamentoProvider>
          <CarrinhoProvider>
            <Carrinho />
          </CarrinhoProvider>
        </PagamentoProvider>
      </Route>
      <Route>
        <Page404 />
      </Route>
    </Switch>
  </UsuarioProvider>
</BrowserRouter>

Nessa solução, precisamos replicar o CarrinhoProvider e o PagamentoProvider nas rotas que precisam dela, e isso vai evitar o problema do <Switch> considerar o Provider como uma rota. Isso deveria gerar um erro de inconsistência de dados, mas como criamos um componente e estamos utilizando apenas um Context.Provider, ele possivelmente não vá gerar problemas.

Criando outro Switch dentro das rotas:

<BrowserRouter>
      <UsuarioProvider>
        <Switch>
          <Route exact path="/">
            <Login />
          </Route>
          <CarrinhoProvider>
            <PagamentoProvider>
              <Switch>
                <Route path="/feira">
                  <Feira />
                </Route>
                <Route path="/carrinho">
                  <Carrinho />
                </Route>
                <Route>
                  <Page404 />
                </Route>
              </Switch>
            </PagamentoProvider>
          </CarrinhoProvider>
        </Switch>
      </UsuarioProvider>
    </BrowserRouter>

Nesse caso:

  1. O UsuárioProvider passou para cima do Switch, pois ele provê estado para todas as nossas rotas
  2. O Router passa pelo Switch, e quando ele não para no Login ele vê os Providers como uma rota
  3. Depois dos Providers, colocamos outro Switch para se não tiver nenhuma rota dentro dele, ele mostrar o 404.

Esse caso solucionaria o problema, mas você teria que criar talvez várias rotas 404, isso pode ser um problema.

Nenhuma das soluções é mais certa que a outra, apenas adote a que for melhor para você na situação em que se encontra.

Bons estudos!!

Muito obrigado pela resposta, professor! Esclareceu bastante!!

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software