📚 Módulo 10: Mobile - Setup do React Native com Expo, Estrutura e Expo Router

Neste módulo, iniciaremos a jornada de expansão móvel da TecLoja 03. Em vez de usar uma abordagem híbrida baseada em WebView, desenvolveremos um aplicativo completamente nativo utilizando o React Native com Expo (TypeScript). O app consumirá diretamente a API REST construída em NestJS e persistida no banco de dados Neon PostgreSQL nos módulos anteriores.

Estruturaremos o ambiente móvel local com Expo CLI, configuraremos o sistema moderno de navegação baseada em arquivos (Expo Router) e faremos a integração de comunicação com o backend.


🗺️ 1. Arquitetura Nativa Decoplada (NestJS + React Native)

Diferente de um webapp híbrido, o React Native renderiza componentes físicos do sistema operacional Android/iOS em tempo real. Veja o fluxo de dados entre o app e nossa API corporativa:

flowchart TD
    %% Styling
    classDef reactNative fill:#61DAFB,stroke:#20232A,stroke-width:2px,color:#000;
    classDef route fill:#8A2BE2,stroke:#4B0082,stroke-width:2px,color:#fff;
    classDef nest fill:#E0234E,stroke:#9F1239,stroke-width:2px,color:#fff;
    classDef pg fill:#336791,stroke:#244967,stroke-width:2px,color:#fff;

    subgraph Mobile_Client ["📱 Cliente Mobile (React Native + Expo)"]
        A[Expo App Core]:::reactNative --> B[Expo Router: Tabs / Stack]:::route
        B --> C[Fetch / Axios Request]:::reactNative
    end

    subgraph Backend_Server ["⚙️ Servidor Backend (NestJS)"]
        C <-->|HTTP / JWT Bearer| D[Controllers / Routes]:::nest
        D <-->|Prisma ORM ACID| E[PostgreSQL Neon]:::pg
    end

⚙️ 2. Inicialização do Projeto Móvel Independente

No modelo multirepo, o aplicativo móvel da TecLoja 03 deve ser desenvolvido em um novo repositório independente do GitHub ou em uma pasta paralela ao frontend web Vite.

Abra o seu terminal na pasta raiz do curso (fora da pasta web) e execute a CLI oficial do Expo para criar o esqueleto TypeScript:

# Criar o app mobile a partir do template recomendado em TypeScript
npx create-expo-app@latest tecloja-mobile --template blank-typescript

Acesse a pasta recém-criada e instale os pacotes necessários para roteamento, estilização nativa e chamadas de API:

cd tecloja-mobile

# Instalar dependências para navegação e consumo HTTP
npx expo install expo-router react-native-safe-area-context react-native-screens expo-linking expo-constants expo-status-bar
npm install axios

Configurando o Expo Router (app/_layout.tsx)

O Expo Router mapeia de forma automatizada os arquivos dentro de uma pasta chamada app em telas físicas do aplicativo (idêntico ao funcionamento de rotas do Next.js).

  1. Crie a pasta /app/ na raiz do projeto.
  2. Crie o arquivo principal de configuração /app/_layout.tsx:
import { Stack } from 'expo-router';
import { StatusBar } from 'expo-status-bar';

export default function Layout() {
  return (
    <>
      <StatusBar style="light" backgroundColor="#0f172a" />
      <Stack
        screenOptions={{
          headerStyle: {
            backgroundColor: '#0f172a', // Slate 900
          },
          headerTintColor: '#38bdf8', // Sky 400 (Neon accent)
          headerTitleStyle: {
            fontWeight: 'bold',
          },
          contentStyle: {
            backgroundColor: '#0f172a',
          }
        }}
      />
    </>
  );
}

🧭 3. Criação da Estrutura de Navegação em Abas (Tabs)

Para a navegação interna principal, utilizaremos o padrão de abas inferiores (Bottom Tabs). Crie o arquivo /app/(tabs)/_layout.tsx:

import { Tabs } from 'expo-router';
import { View, Text } from 'react-native';

export default function TabsLayout() {
  return (
    <Tabs
      screenOptions={{
        tabBarStyle: {
          backgroundColor: '#0f172a',
          borderTopColor: '#1e293b',
        },
        tabBarActiveTintColor: '#38bdf8',
        tabBarInactiveTintColor: '#64748b',
        headerShown: false,
      }}
    >
      <Tabs.Screen
        name="index"
        options={{
          title: 'Produtos',
          // Omitindo ícone para fins didáticos simplificados
        }}
      />
      <Tabs.Screen
        name="carrinho"
        options={{
          title: 'Carrinho',
        }}
      />
      <Tabs.Screen
        name="perfil"
        options={{
          title: 'Perfil',
        }}
      />
    </Tabs>
  );
}

E crie a tela inicial de listagem de produtos em /app/(tabs)/index.tsx:

import { StyleSheet, Text, View } from 'react-native';

export default function ProdutosScreen() {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>🛒 TecLoja 03 - Catálogo</Text>
      <Text style={styles.subtitle}>Os melhores eletrônicos e produtos de tecnologia do mercado.</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 24,
    backgroundColor: '#0f172a',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#38bdf8',
    marginBottom: 8,
  },
  subtitle: {
    fontSize: 16,
    color: '#94a3b8',
    textAlign: 'center',
  },
});

🔗 4. Estabelecendo Conexão com a API NestJS

O emulador Android roda em uma máquina virtual isolada da sua máquina de desenvolvimento. Portanto, se você tentar bater em localhost:3000 (porta do NestJS), o emulador tentará se conectar a si mesmo e falhará.

Para acessar a API local, usaremos o IP especial de loopback 10.0.2.2 no Android, ou o IP físico de rede local do computador caso esteja testando em um celular físico real conectado ao mesmo Wi-Fi.

Criando o Cliente de API em services/api.ts

import axios from 'axios';
import { Platform } from 'react-native';

// IP especial do emulador do Android ou Localhost para iOS/Produção
const API_URL = Platform.OS === 'android' 
  ? 'http://10.0.2.2:3000' 
  : 'http://localhost:3000';

export const api = axios.create({
  baseURL: API_URL,
  timeout: 10000,
});

✅ Pré-Requisitos deste Módulo

Antes de iniciar a compilação local, certifique-se de que:


🤔 Por que fizemos assim?


🔍 Checkpoint

  1. Execução do Servidor Expo: Rode npx expo start no terminal do projeto mobile e confirme se o QR Code e o menu interativo são gerados no console.
  2. Abertura no Aparelho: Escaneie o QR Code usando a câmera do celular (iOS) ou o app Expo Go (Android) e confirme se a tela preta com o texto da TecLoja 03 renderiza corretamente na tela do celular.

⚠️ Erros Comuns

Erro Causa Solução
Network Error ao disparar chamadas HTTP O aplicativo tentou bater em localhost:3000 ou a API NestJS está inativa. Certifique-se de que o NestJS está de pé na porta 3000 e que você configurou o IP 10.0.2.2 para o emulador de Android ou o IP local físico da rede (ex: 192.168.1.15) no caso de dispositivo físico.
O Expo Router não encontra as telas ou exibe Route "/" not found A pasta /app foi criada com nome incorreto ou o arquivo de inicialização do layout está ausente. Mantenha as telas estritamente sob a pasta /app/ na raiz do projeto, respeitando a grafia em letras minúsculas.
Unable to resolve module ... Algum módulo foi importado no código sem que a dependência tenha sido devidamente instalada. Rode npx expo install nome-do-modulo para garantir a versão compatível com a SDK do Expo em execução.

Voltar para o Sumário