Injeção de dependência em dispositivos móveis significa passar dependências - clientes de API, armazenamento, análise - em vez de importar singletons. Equipes React Native obtêm serviços testáveis com funções de fábrica, contexto React e limites de módulo - não Dagger, Spring ou um localizador de serviço global.
// src/shared/api/createApiClient.tsexport type ApiClient = { get<T>(path: string): Promise<T>;};export function createApiClient(baseUrl: string): ApiClient { return { async get<T>(path: string) { const response = await fetch(`${baseUrl}${path}`); if (!response.ok) throw new Error(`GET ${path} failed`); return response.json() as Promise<T>; }, };}
// src/features/orders/api/ordersApi.tsimport type { Order } from "@/entities/order";import type { ApiClient } from "@/shared/api/createApiClient";export type OrdersApi = { list(): Promise<Order[]>;};export function createOrdersApi(client: ApiClient): OrdersApi { return { list: () => client.get<Order[]>("/orders"), };}
Contexto "god" com 40 serviços - Tudo re-renderiza em qualquer alteração de substituição. Correção: Divida por recurso ou use objetos de serviço estáveis useMemo.
Criação de novas instâncias de serviço a cada renderização - Quebra dependências useCallback e re-busca infinitamente. Correção: Memorize serviços no provedor com useMemo(() => create..., [baseUrl]).
Importação de adaptadores concretos em casos de uso - Inverte a arquitetura limpa. Correção: Casos de uso aceitam interfaces de porta; apenas a raiz de composição importa restAuthGateway.
Surpresas de hoisting do jest.mock - O caminho do mock deve corresponder à importação exata. Correção: Prefira a prop overrides do provedor em vez de mocks de módulo quando possível.
URLs de serviço do Expo Go vs. build de desenvolvimento - Ramos __DEV__ ocultos em fábricas. Correção:getAppConfig().apiBaseUrl de app.config.ts extra por variante.
Singleton de análise em todos os arquivos - Spam de eventos não testável. Correção:AnalyticsPort injetado; implementação noop em testes.
tsyringe para três serviços - Dor de metadados de reflexão no Metro. Correção: Fábricas simples até que você tenha mais de 20 tipos conectados.
Os aplicativos React Native precisam de um framework DI?
Não. Funções de fábrica mais contexto React cobrem 95% das necessidades móveis. Containers adicionam indireção sem resolver problemas específicos de RN (bundling do Metro, Fast Refresh).
O que é a raiz de composição?
O único lugar onde implementações concretas se ligam a abstrações - tipicamente app/_layout.tsx ou AppServicesProvider. Nenhum outro arquivo deve chamar createRestAuthGateway com URLs de produção.
Como testar hooks que usam clientes de API?
Envolva com AppServicesProvider overrides={{ ordersApi: mock }}. Alternativamente, passe a API como um argumento de hook apenas em testes.
Contexto vs Zustand para serviços?
Contexto conecta instâncias de serviço imutáveis (API, armazenamento). Zustand mantém estado mutável do aplicativo (carrinho, sessão). Não armazene clientes de busca no Zustand, a menos que eles contenham tokens de sessão que mudam.
Posso usar loaders do expo-router para DI?
Expo Router não tem loaders RSC. Conecte serviços em provedores de layout raiz - não por rota, a menos que as deps com escopo de rota sejam verdadeiramente isoladas.
Como as variantes de ambiente obtêm APIs diferentes?
getAppConfig() lê extra de app.config.ts - a raiz de composição passa o baseUrl correto ao criar clientes. Sem if no código do recurso.
E sobre @tanstack/react-query?
Injete um QueryClient via contexto (QueryClientProvider integrado). Adaptadores de repositório alimentam funções de consulta - queryFn: () => ordersApi.list().
O jest.mock é ruim?
Aceitável para testes de integração. Prefira overrides do provedor para testes unitários - mais claro e tipado.
Como evitar importações circulares com DI?
Portas vivem em domain/ports.ts. Adaptadores importam portas + entidades. A raiz de composição importa adaptadores. Recursos importam portas através do contexto - nunca adaptadores do domínio.
O SecureStore deve ser injetado?
Sim - envolva em uma porta TokenStorage. Testes usam armazenamento em memória; produção usa createSecureTokenStorage().
Fast Refresh com provedores de contexto?
Alterar a implementação do provedor recarrega a quente bem. Alterar a forma do contexto pode exigir recarga total - mantenha o tipo AppServices estável.
Múltiplos aplicativos em monorepo - DI compartilhada?
Pacotes compartilhados packages/services exportam fábricas; cada raiz de composição apps/* passa a configuração específica do aplicativo. Não compartilhe um singleton entre aplicativos.
Quando uma biblioteca DI faz sentido?
Raramente em RN. Considere quando portar padrões de equipes de backend grandes ou quando você tem mais de 30 interfaces conectadas com testes de contrato automatizados - ainda avalie o custo do Metro primeiro.
Como a DI se relaciona com a arquitetura limpa?
Portas são interfaces; adaptadores são implementações; a raiz de composição as conecta. Casos de uso recebem deps como argumentos de função - a forma mais pura de injeção.