📚 Pré-requisitos Teóricos: este projeto consome os serviços da Parte 01 — Spring Boot API e a infraestrutura conteinerizada da Parte 05 — Docker + PostgreSQL.

📝 Projeto Lista de Tarefas 07 — Spring Boot + React ➔ React Native

Seja muito bem-vindo à Parte 07 da série de projetos Lista de Tarefas!

Nesta etapa prática, você aprenderá a dominar a segunda grande trilha de equivalência entre desenvolvimento Web e Mobile Híbrido / Cross-platform:

\[\text{Web SPA (React 19 + Vite)} \longrightarrow \text{Mobile Cross-Platform (React Native + Expo)}\]

💡 “Construa interfaces com componentes e deixe o ecossistema complementar.”

Enquanto na Web tradicional montamos interfaces manipulando elementos HTML (<div>, <button>, <input>) renderizados através da árvore do Virtual DOM nos navegadores, no ecossistema mobile com React Native utilizamos o mesmo modelo mental de componentes e estados (useState, useEffect), porém renderizando componentes nativos reais de Android e iOS (<View>, <Text>, <TouchableOpacity>, <FlatList>) através do motor de layout Yoga Flexbox e empacotados com a produtividade do Expo.


🗺️ 1. Visão Geral da Arquitetura & Papel no Ecossistema

Tanto a aplicação Web SPA em React quanto o cliente móvel em React Native operam como consumidores diretos da nossa Fonte Única da Verdade (SSOT): a API REST desenvolvida em Spring Boot na porta 8080, padronizada sob o contrato canônico { id, descricao, concluida }.

Ecossistema React Web para React Native Mobile

Por que a combinação React + React Native (Expo)?


⚡ 2. Fluxo Reativo, Gestos Mobile e Resolução de Plataforma

Um dos aspectos cruciais do cliente móvel é a resolução dinâmica de rede para alcançar a API na máquina de desenvolvimento:

Ciclo de Sincronização Mobile React Native

  1. No Navegador Web / SPA: O app dispara requisições HTTP para http://localhost:8080/api/tarefas.
  2. No Emulador Android (AVD): O emulador Android roda em uma máquina virtual isolada onde localhost representa o próprio celular emulado. Para alcançar a API que roda no computador, o serviço utiliza o alias de rede: \(\text{URL no Emulador Android} = \mathbf{http://10.0.2.2:8080/api/tarefas}\)
  3. No Dispositivo Físico (Expo Go via Wi-Fi): Quando conectado na mesma rede sem fio, o app utiliza o IP privado do computador hospedeiro (ex: http://192.168.1.50:8080/api/tarefas).

📑 3. Engenharia de Software & Especificação de Requisitos

3.1. Histórias de Usuário (Web & Mobile React Native)

3.2. Requisitos Funcionais (RF)

ID Descrição Endpoint REST
RF-R01 Consultar e exibir todas as tarefas cadastradas com suporte a pull-to-refresh (RefreshControl). GET /api/tarefas
RF-R02 Cadastrar nova tarefa com descrição preenchida e status inicial pendente. POST /api/tarefas
RF-R03 Alternar o estado de conclusão (concluida = true/false) de forma atômica. PATCH /api/tarefas/{id}/status
RF-R04 Modificar a descrição de uma tarefa existente com pré-carregamento dos dados. PUT /api/tarefas/{id}
RF-R05 Deletar permanentemente uma tarefa após confirmação do usuário. DELETE /api/tarefas/{id}

3.3. Requisitos Não-Funcionais (RNF)

ID Categoria Descrição
RNF-R01 Performance de Lista O cliente mobile deve utilizar FlatList com reciclagem de células de memória para suportar listas volumosas.
RNF-R02 Resolução Dinâmica O módulo de rede (api.js) deve chavear automaticamente para 10.0.2.2:8080 caso detecte ambiente Android.
RNF-R03 Feedback Tátil & Diálogos Operações destrutivas devem utilizar alertas nativos do sistema (Alert.alert no mobile e window.confirm na web).
RNF-R04 Ergonomia Móvel A tela principal deve conter um Floating Action Button (FAB) com elevação e posicionamento ergonômico no canto inferior direito.
RNF-R05 Contrato Canônico Toda a comunicação com a API deve trafegar exclusivamente o payload { id, descricao, concluida }.

3.4. Casos de Uso do Sistema

flowchart LR
    User(("👤 Usuário Web / Mobile"))

    subgraph "Aplicação React / React Native"
        UC01["UC01: Listar Tarefas em FlatList"]
        UC02["UC02: Inserir Nova Tarefa via FAB"]
        UC03["UC03: Alternar Conclusão da Tarefa"]
        UC04["UC04: Editar Tarefa em Tela Própria"]
        UC05["UC05: Excluir Tarefa com Diálogo Nativo"]
    end

    User --> UC01
    User --> UC02
    User --> UC03
    User --> UC04
    User --> UC05

UC01: Listar Tarefas em FlatList

UC02: Inserir Nova Tarefa via FAB

UC03: Alternar Conclusão da Tarefa

UC04: Editar Tarefa em Tela Própria

UC05: Excluir Tarefa com Diálogo Nativo


3.5. Matriz de Rastreabilidade (RTM)

Caso de Uso História de Usuário Requisito Funcional Requisito Não-Funcional Arquivo Responsável
UC01 US-R01 RF-R01 RNF-R01, RNF-R02, RNF-R05 HomeScreen.js, HomePage.jsx
UC02 US-R02 RF-R02 RNF-R04, RNF-R05 TaskFormScreen.js, TaskFormPage.jsx
UC03 US-R03 RF-R03 RNF-R05 HomeScreen.js, TaskService.js
UC04 US-R04 RF-R04 RNF-R05 TaskFormScreen.js, TaskFormPage.jsx
UC05 US-R05 RF-R05 RNF-R03, RNF-R05 HomeScreen.js, Alert.alert

🛠️ 4. Estrutura de Pastas da Parte 07

O projeto organiza-se em dois módulos front-end complementares consumindo a mesma API central:

fullstack_tarefas_07_spring_react/
├── assets/
│   ├── arquitetura_react_native_ecosystem.svg  ← Diagrama conceitual React Web para Mobile
│   └── fluxo_sincronizacao_expo_api.svg        ← Diagrama do ciclo de rede com Expo
├── web-react/                                   ← Web SPA em React 19 + Vite
│   ├── src/
│   │   ├── pages/
│   │   │   ├── HomePage.jsx                    ← Listagem com filtros e estilo moderno
│   │   │   └── TaskFormPage.jsx                ← Formulário com validação e foco
│   │   ├── services/
│   │   │   ├── api.js                          ← Axios configurado em localhost:8080
│   │   │   └── TaskService.js                  ← Métodos HTTP de CRUD de tarefas
│   │   ├── App.jsx                             ← Configuração de rotas com React Router
│   │   └── main.jsx                            ← Ponto de entrada React 19
│   ├── package.json
│   └── vite.config.js
├── mobile-reactnative/                                     ← Cliente Mobile com React Native + Expo
│   ├── src/
│   │   ├── screens/
│   │   │   ├── HomeScreen.js                   ← FlatList, RefreshControl e FAB
│   │   │   └── TaskFormScreen.js               ← Tela de formulário com Switch de status
│   │   └── services/
│   │       ├── api.js                          ← Resolução inteligente de host (10.0.2.2)
│   │       └── TaskService.js                  ← Cliente REST para tarefas
│   ├── App.js                                  ← Navegação em pilha (Stack Navigator)
│   ├── app.json                                ← Configuração do ecossistema Expo
│   ├── package.json                            ← Dependências React Native e Expo
│   └── README.md                               ← Guia de execução mobile
└── index.md                                    ← Este Guia Padrão Ouro Educacional

💻 5. Implementação Prática & Destaques de Código

5.1. Resolução Dinâmica de Rede no React Native (mobile-reactnative/src/services/api.js)

O serviço detecta a plataforma em tempo de execução via Platform.OS:

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

const getBaseUrl = () => {
    if (Platform.OS === 'android') {
        return 'http://10.0.2.2:8080/api';
    }
    return 'http://localhost:8080/api';
};

const api = axios.create({
    baseURL: getBaseUrl(),
    headers: {
        'Content-Type': 'application/json',
    },
    timeout: 10000,
});

export default api;

5.2. Lista Virtualizada e Pull-to-Refresh (mobile-reactnative/src/screens/HomeScreen.js)

A tela principal do cliente móvel implementa FlatList com RefreshControl:

<FlatList
    data={tasks}
    keyExtractor={item => item.id.toString()}
    renderItem={renderItem}
    refreshControl={
        <RefreshControl
            refreshing={refreshing}
            onRefresh={onRefresh}
            colors={['#6366f1']}
        />
    }
    ListEmptyComponent={
        <View style={styles.emptyContainer}>
            <Text style={styles.emptyTitle}>Nenhuma tarefa encontrada</Text>
            <Text style={styles.emptySub}>Puxe para atualizar ou toque no botão + para adicionar.</Text>
        </View>
    }
    contentContainerStyle={{ paddingBottom: 80 }}
/>

🚀 6. Roteiro de Execução e Homologação

1. Iniciar a API Spring Boot Central (SSOT)

Abra um terminal na pasta do backend oficial:

cd catalogo_projetos/fullstack_tarefas_01_spring_api
./mvnw spring-boot:run

✅ Checkpoint: Acesse http://localhost:8080/api/tarefas no navegador e certifique-se de receber a lista em formato JSON com o modelo { id, descricao, concluida }.

2. Executar o Frontend Web React Tradicional

Em outro terminal:

cd catalogo_projetos/fullstack_tarefas_07_spring_react/frontend
npm install
npm run dev

✅ Checkpoint: Abra http://localhost:5173 no navegador e valide a listagem, os filtros por status, a criação e a exclusão de tarefas.

3. Executar o Cliente Mobile React Native com Expo

Em um terceiro terminal:

cd catalogo_projetos/fullstack_tarefas_07_spring_react/mobile
npm install
npx expo start

✅ Checkpoint: Pressione a para iniciar no emulador Android já aberto. Teste o gesto de pull-to-refresh, a alternância de status tocando no checkbox e a adição de tarefas pelo FAB (+).

4. Matriz de Homologação & Checkpoints de Validação

Checkpoint Ação / Cenário de Teste Critério de Aceite Status
CP-01 Iniciar a API Spring Boot central na porta 8080 Resposta 200 OK com array JSON na rota /api/tarefas. PASS ✅
CP-02 Executar a SPA React na Web via Vite (localhost:5173) Renderização de componentes, exibição de tarefas e filtros de status ativos. PASS ✅
CP-03 Cadastrar e alternar status na Web SPA Tarefa gravada via POST/PUT; refletida em tela instantaneamente. PASS ✅
CP-04 Iniciar cliente mobile via Expo no Emulador (10.0.2.2:8080) FlatList nativa renderiza as mesmas tarefas criadas no navegador web. PASS ✅
CP-05 Executar gesto de Pull-to-Refresh no React Native Indicador giratório nativo acionado; dados recarregados da API central. PASS ✅
CP-06 Cadastrar tarefa pelo botão FAB (+) no Expo Nova tarefa persistida e renderizada sem perda de contexto ou reload. PASS ✅

🧯 7. Tabela de Troubleshooting

Sintoma Causa Mais Provável Solução Recomendada
Network Error no emulador Android O app tentou conectar em localhost:8080 ao invés de 10.0.2.2:8080. Verifique se Platform.OS === 'android' está configurado em src/services/api.js.
Erro de CORS no navegador Web A API Spring Boot não permitiu a origem do Vite (:5173) ou Expo Web. Verifique se a anotação @CrossOrigin("*") está presente na API central.
Tela branca ou erro no React Router Versão de dependência incompatível no Vite. Execute npm install limpo na pasta web-react/.
Falha de conexão no celular físico O celular não consegue resolver 10.0.2.2 ou localhost. Altere temporariamente a URL no api.js para o IP do seu computador na rede Wi-Fi (ex: 192.168.1.X:8080).

🔮 8. Próxima Etapa: Parte 08 — Spring Boot + Angular Standalone ➔ Ionic Framework

Com a equivalência React ➔ React Native concluída com sucesso, avançaremos para o terceiro vértice da trilha: