# Expo Router no React Native: Guia Completo de Navegação Baseada em Arquivos > Guia completo do Expo Router para React Native com navegação baseada em arquivos, rotas dinâmicas, tabs, modais, rotas tipadas e proteção de rotas. Exemplos práticos com código. - Published: 2026-04-18 - Updated: 2026-04-18 - Author: SharpSkill - Tags: react-native, expo, expo-router, navigation, mobile-development, tutorial - Reading time: 9 min --- O Expo Router transformou a forma como aplicações React Native lidam com navegação ao trazer o conceito de roteamento baseado em arquivos — um padrão amplamente consolidado na web com frameworks como Next.js — para o ecossistema mobile. Em vez de configurar manualmente stacks de navegação com objetos e arrays, os desenvolvedores agora podem criar rotas simplesmente adicionando arquivos na pasta `app/`. Cada arquivo se torna automaticamente uma rota, e a estrutura de diretórios define a hierarquia de navegação. Essa abordagem reduz drasticamente o boilerplate, melhora a previsibilidade do código e unifica a experiência de desenvolvimento entre plataformas web, iOS e Android. > **Configuração Rápida** > > Para iniciar um projeto com Expo Router já configurado, basta executar `npx create-expo-app@latest --template tabs`. O template inclui navegação por tabs, layouts aninhados e TypeScript pré-configurados. O Expo Router v4+ exige Expo SDK 53 ou superior. ## Como Funciona o Roteamento Baseado em Arquivos no Expo Router O princípio fundamental do Expo Router é simples: a estrutura de arquivos dentro do diretório `app/` define todas as rotas da aplicação. Não existe um arquivo central de configuração de rotas. Cada arquivo `.tsx` ou `.ts` exporta um componente React que se torna a tela correspondente àquele caminho. O arquivo `index.tsx` na raiz do diretório `app/` representa a rota inicial da aplicação: ```tsx // app/index.tsx import { View, Text, StyleSheet } from 'react-native'; import { Link } from 'expo-router'; export default function HomeScreen() { return ( Welcome Home Go to Profile Open Settings ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center' }, title: { fontSize: 24, fontWeight: 'bold', marginBottom: 20 }, link: { fontSize: 16, color: '#2563eb', marginTop: 10 }, }); ``` O componente `Link` do Expo Router funciona de maneira análoga às tags `` na web. Ele recebe uma prop `href` com o caminho de destino e realiza a navegação de forma declarativa. Ao contrário do React Navigation tradicional, onde seria necessário chamar `navigation.navigate('Profile')`, o Expo Router utiliza URLs como cidadãos de primeira classe. Essa abordagem traz benefícios imediatos: deep linking funciona automaticamente, e a mesma URL funciona tanto na web quanto no mobile. ## Estrutura de Projeto e Arquivos de Layout A organização de diretórios no Expo Router segue convenções claras. Pastas representam segmentos de rota, e arquivos `_layout.tsx` controlam como as telas filhas são renderizadas dentro de cada segmento. Uma estrutura típica de projeto se apresenta da seguinte forma: ``` app/ ├── _layout.tsx # Root layout (Stack navigator) ├── index.tsx # "/" route ├── about.tsx # "/about" route ├── (tabs)/ │ ├── _layout.tsx # Tab navigator layout │ ├── index.tsx # First tab ("/") │ ├── explore.tsx # "/explore" tab │ └── profile.tsx # "/profile" tab ├── settings/ │ ├── _layout.tsx # Settings stack layout │ ├── index.tsx # "/settings" │ └── notifications.tsx # "/settings/notifications" └── [id].tsx # Dynamic route ("/:id") ``` O arquivo `_layout.tsx` na raiz define o navegador principal da aplicação. Esse layout encapsula todas as rotas e determina o tipo de navegação utilizado (Stack, Tabs ou Drawer): ```tsx // app/_layout.tsx import { Stack } from 'expo-router'; export default function RootLayout() { return ( ); } ``` Os grupos de rotas, identificados por parênteses como `(tabs)`, permitem organizar arquivos sem afetar a URL final. Uma rota dentro de `(tabs)/explore.tsx` é acessada como `/explore`, e não como `/(tabs)/explore`. Essa funcionalidade permite agrupar rotas logicamente sem poluir a estrutura de URLs da aplicação. ## Construindo Navegação por Tabs com Expo Router A navegação por tabs é o padrão mais comum em aplicações mobile. O Expo Router implementa tabs através de um arquivo `_layout.tsx` dentro de um grupo de rotas, utilizando o componente `Tabs`: ```tsx // app/(tabs)/_layout.tsx import { Tabs } from 'expo-router'; import { Ionicons } from '@expo/vector-icons'; export default function TabsLayout() { return ( ( ), }} /> ( ), }} /> ( ), }} /> ); } ``` Cada `Tabs.Screen` corresponde a um arquivo dentro do grupo `(tabs)/`. A propriedade `name` deve coincidir exatamente com o nome do arquivo (sem a extensão). O Expo Router trata cada tab como uma rota independente com seu próprio histórico de navegação, permitindo que o usuário navegue para sub-rotas dentro de cada tab sem perder o estado das demais. ## Rotas Dinâmicas e Parâmetros de Rota Rotas dinâmicas permitem criar telas que respondem a parâmetros variáveis na URL. No Expo Router, basta nomear o arquivo com colchetes para criar um segmento dinâmico: ```tsx // app/product/[id].tsx import { View, Text, StyleSheet } from 'react-native'; import { useLocalSearchParams, Stack } from 'expo-router'; export default function ProductScreen() { const { id } = useLocalSearchParams<{ id: string }>(); return ( Product Details Product ID: {id} ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center' }, title: { fontSize: 24, fontWeight: 'bold' }, id: { fontSize: 16, color: '#64748b', marginTop: 8 }, }); ``` O hook `useLocalSearchParams` extrai os parâmetros da URL atual de forma tipada. Para rotas como `/product/42`, o valor de `id` retorna `"42"`. Esse hook é local ao componente, garantindo que cada tela mantenha seus próprios parâmetros mesmo em cenários de navegação complexos. Para capturar múltiplos segmentos de URL, o Expo Router suporta rotas catch-all utilizando a sintaxe de spread: ```tsx // app/docs/[...slug].tsx import { useLocalSearchParams } from 'expo-router'; import { View, Text } from 'react-native'; export default function DocsScreen() { const { slug } = useLocalSearchParams<{ slug: string[] }>(); // /docs/getting-started/installation → slug = ['getting-started', 'installation'] return ( Documentation Path: {slug?.join(' → ')} ); } ``` A rota `[...slug].tsx` captura qualquer quantidade de segmentos após `/docs/`, retornando-os como um array de strings. Esse padrão é especialmente valioso para sistemas de documentação, blogs ou qualquer estrutura com hierarquia de profundidade variável. ## Rotas Tipadas para Segurança em Tempo de Compilação O Expo Router oferece suporte nativo a rotas tipadas com TypeScript, gerando automaticamente tipos para todas as rotas da aplicação. Essa funcionalidade elimina erros de digitação em URLs e fornece autocompletar no editor de código. Para habilitar rotas tipadas, basta configurar o `app.json`: ```json { "expo": { "experiments": { "typedRoutes": true } } } ``` Com essa configuração ativa, o Expo Router gera um arquivo de tipos que mapeia todas as rotas disponíveis. Qualquer referência a uma rota inexistente gera um erro de compilação: ```tsx // app/checkout.tsx — typed navigation example import { Link } from 'expo-router'; import { View, Text, Pressable } from 'react-native'; import { router } from 'expo-router'; export default function CheckoutScreen() { const handleComplete = () => { // TypeScript validates this route exists at compile time router.push('/order-confirmation'); }; return ( Checkout {/* TypeScript error if "/invalid-route" doesn't exist */} Complete Order Process Payment ); } ``` Essa camada de segurança de tipos se mostra particularmente relevante em projetos de grande porte, onde dezenas de telas e centenas de links tornam erros manuais praticamente inevitáveis. O TypeScript detecta rotas inválidas durante o desenvolvimento, antes mesmo de executar a aplicação. ## Telas Modais e Opções de Apresentação Modais são telas que se sobrepõem ao conteúdo existente, geralmente utilizadas para formulários de criação, confirmações ou detalhes rápidos. O Expo Router implementa modais através de opções de apresentação no layout: ```tsx // app/_layout.tsx — with modal support import { Stack } from 'expo-router'; export default function RootLayout() { return ( ); } ``` A tela correspondente ao modal recebe toda a funcionalidade padrão de uma rota, incluindo deep linking e parâmetros: ```tsx // app/create-post.tsx import { View, TextInput, Pressable, Text, StyleSheet } from 'react-native'; import { router } from 'expo-router'; import { useState } from 'react'; export default function CreatePostModal() { const [title, setTitle] = useState(''); const [body, setBody] = useState(''); const handleSubmit = () => { // Save post logic here router.back(); // Dismiss modal }; return ( Publish ); } const styles = StyleSheet.create({ container: { flex: 1, padding: 20, backgroundColor: '#ffffff' }, input: { borderWidth: 1, borderColor: '#e2e8f0', borderRadius: 8, padding: 12, fontSize: 16, marginBottom: 12, }, bodyInput: { height: 200, textAlignVertical: 'top' }, button: { backgroundColor: '#2563eb', padding: 16, borderRadius: 8, alignItems: 'center', }, buttonText: { color: '#ffffff', fontSize: 16, fontWeight: 'bold' }, }); ``` A chamada `router.back()` fecha o modal e retorna à tela anterior. No iOS, o gesto de swipe down para fechar funciona automaticamente quando a apresentação é configurada como modal. ## Navegação Programática e a API do Router Além da navegação declarativa com o componente `Link`, o Expo Router disponibiliza uma API imperativa completa através do objeto `router`. Essa API permite navegar em resposta a eventos, resultados de chamadas assíncronas ou lógica condicional: ```tsx import { router } from 'expo-router'; // Push a new screen onto the stack router.push('/profile/settings'); // Replace the current screen (no back button) router.replace('/dashboard'); // Go back to the previous screen router.back(); // Navigate with parameters router.push({ pathname: '/product/[id]', params: { id: '42', source: 'search' }, }); // Reset the navigation state entirely router.dismissAll(); router.replace('/'); ``` A distinção entre `router.push` e `router.replace` merece atenção especial. O método `push` adiciona uma nova entrada ao histórico de navegação, permitindo que o usuário retorne com o botão voltar. Já o `replace` substitui a entrada atual, sendo ideal para fluxos de autenticação onde o retorno à tela de login após o login bem-sucedido seria indesejado. > **Navegação vs Redirecionamento** > > O `router.push` e o `router.replace` operam no lado do cliente. Para redirecionamentos no lado do servidor (SSR/SSG na web), deve-se utilizar a função `redirect` do Expo Router. Em rotas puramente mobile, `router.replace` dentro de um `useEffect` atende à maioria dos cenários de redirecionamento. ## Middleware e Proteção de Rotas Proteger rotas contra acesso não autorizado é um requisito fundamental em aplicações reais. O Expo Router oferece dois mecanismos principais para isso: middleware (na web) e layouts de autenticação (cross-platform). O middleware funciona exclusivamente em contextos web e permite interceptar requisições antes da renderização: ```typescript // app/_middleware.ts import { redirect } from 'expo-router/server'; export function GET(request: Request) { const token = request.headers.get('authorization'); if (!token) { return redirect('/login'); } } ``` Para uma abordagem cross-platform que funcione tanto na web quanto no mobile, o padrão recomendado envolve um layout de autenticação que verifica a sessão do usuário e redireciona quando necessário: ```tsx // app/(authenticated)/_layout.tsx import { Redirect, Stack } from 'expo-router'; import { useAuth } from '@/hooks/useAuth'; import { ActivityIndicator, View } from 'react-native'; export default function AuthenticatedLayout() { const { user, isLoading } = useAuth(); if (isLoading) { return ( ); } if (!user) { return ; } return ( ); } ``` Todas as rotas dentro do grupo `(authenticated)/` passam automaticamente pela verificação de autenticação definida no layout. Se o usuário não estiver logado, o componente `Redirect` redireciona para a tela de login. Caso o estado de autenticação ainda esteja sendo carregado, um indicador de atividade evita flashes de conteúdo indesejados. > **Atenção à Plataforma** > > O middleware (`_middleware.ts`) funciona exclusivamente na web. Para proteção de rotas em iOS e Android, os layouts com verificação de autenticação representam a abordagem recomendada. Essa distinção exige que aplicações multiplataforma implementem ambas as estratégias quando necessário. ## Conclusao O Expo Router consolidou-se como a solucao de referencia para navegacao em aplicacoes React Native modernas. Ao adotar o roteamento baseado em arquivos, o framework elimina camadas de configuracao manual e alinha o desenvolvimento mobile com as praticas ja estabelecidas no ecossistema web. Os principais aspectos abordados neste guia incluem: - O roteamento baseado em arquivos transforma a estrutura de diretorios em rotas automaticas, eliminando configuracao manual de navegacao - Arquivos `_layout.tsx` controlam a renderizacao das telas filhas e definem o tipo de navegacao (Stack, Tabs, Drawer) - Grupos de rotas com parenteses `(tabs)` organizam arquivos sem impactar a URL final - Rotas dinamicas com `[id].tsx` e catch-all com `[...slug].tsx` capturam parametros de URL de forma tipada - Rotas tipadas com TypeScript detectam erros de navegacao em tempo de compilacao - Modais sao implementados via opcoes de apresentacao no layout, com suporte completo a deep linking - A API `router` oferece navegacao programatica com `push`, `replace`, `back` e `dismissAll` - A protecao de rotas combina middleware (web) e layouts de autenticacao (cross-platform) para controle de acesso --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/pt/blog/react-native/expo-router-react-native-file-based-navigation-guide