react native

Arquitetura Mobile Moderna com React Native: Guia Completo – Parte I

Uma jornada prática através dos padrões MVVM, Dependency Injection e Context API para criar apps escaláveis


Desenvolver aplicativos móveis modernos vai muito além de apenas escrever código que funciona. É sobre criar uma arquitetura sólida que seja escalável, testável e mantenível ao longo do tempo. Hoje vamos mergulhar em uma stack completa que combina o melhor do React Native com padrões arquiteturais avançados.

O que você vai aprender nesta série

  • Parte I (este post): Fundamentos da arquitetura, MVVM com MobX e organização de pastas
  • Parte II: Dependency Injection, Repository Pattern e implementação prática

Vamos usar como base um projeto real que implementa estas tecnologias:

  • React Native + Expo para desenvolvimento mobile
  • TypeScript para tipagem estática
  • MobX para gerenciamento de estado reativo
  • Inversify para dependency injection
  • RxJS para programação reativa

A Base: Organização de Pastas que Faz Sentido

Antes de falar sobre padrões, vamos entender como organizar um projeto mobile de forma que sua equipe (e você mesmo daqui 6 meses) consiga navegar facilmente:

src/
├── components/          # Componentes reutilizáveis
├── contexts/           # Estados globais com ViewModels
│   ├── auth/          # Autenticação
│   ├── core/          # Funcionalidades centrais
│   └── push/          # Notificações
├── core/              # Infraestrutura do app
│   ├── di/           # Dependency Injection
│   ├── networking/   # API e interceptors
│   └── storage/      # Persistência de dados
├── services/         # Repositórios e lógica de negócio
└── types/           # Definições TypeScript

Por que essa estrutura funciona?

  1. Separação clara de responsabilidades: Cada pasta tem um propósito específico
  2. Escalabilidade: Fácil adicionar novos contextos ou serviços
  3. Facilita testes: Cada camada pode ser testada independentemente
  4. Time-friendly: Novos desenvolvedores encontram rapidamente o que procuram

MVVM: O Coração da Nossa Arquitetura

O padrão Model-View-ViewModel (MVVM) é perfeito para aplicações React Native porque separa claramente:

  • View: Componentes React (UI)
  • ViewModel: Lógica de apresentação e estado
  • Model: Dados e regras de negócio

Como isso funciona na prática?

Vamos ver um exemplo real do nosso AuthViewModel:

@injectable()
export class AuthViewModel {
  // Estados observáveis do MobX
  phone: string = '';
  loading?: string;
  authenticated: boolean | null = null;

  constructor(
    @inject(DI_TYPES.AuthRepo) private authRepo: AuthRepo
  ) {
    makeObservable(this, {
      phone: observable,
      loading: observable,
      authenticated: observable,
      onPhoneChanged: action,
      setLoading: action,
      isPhoneValid: computed,
    });
  }

  // Ações que modificam o estado
  onPhoneChanged = (phone: string) => {
    this.phone = phone;
  };

  // Estados computados
  get isPhoneValid(): boolean {
    return this.phone ? isValidPhone(this.phone) : false;
  }

  // Lógica de negócio
  onLoginSubmitted = () => {
    this.setLoading('login.request.sendingConfirmation');

    this.authRepo.sendOtp$(this.fullPhoneNumber, this.region?.cca2)
      .subscribe({
        next: (response) => {
          this.clearLoading();
          // Navegar para próxima tela
        },
        error: (error) => {
          this.setError(error.message);
        }
      });
  };
}

Vantagens do MVVM com MobX

  1. Reatividade automática: Quando phone muda, a UI se atualiza automaticamente
  2. Testabilidade: Você pode testar toda a lógica sem renderizar componentes
  3. Reutilização: O mesmo ViewModel pode ser usado em diferentes telas
  4. Debugging: Estados centralizados facilitam o debug

Context API: Distribuindo Estado de Forma Inteligente

O React Context é nossa ponte entre ViewModels e componentes. Vamos ver como implementar:

// core.provider.tsx
const CoreContext = createContext<CoreViewModel>(undefined!);

export const CoreProvider = ({ children }: { children: React.ReactNode }) => {
  const vm = useMemo(() => new CoreViewModel(AppState.currentState), []);

  useEffect(() => {
    return vm.onMount();
  }, [vm]);

  return <CoreContext.Provider value={vm}>{children}</CoreContext.Provider>;
};

export const useCore = () => {
  const context = useContext(CoreContext);
  if (!context) {
    throw new Error('useCore must be used within a CoreProvider');
  }
  return context;
};

Hook personalizado para observar estado da app

export const useAppFocus = (effect: (focus: AppFocus) => void) => {
  const vm = useCore();

  const stableEffect = useCallback(effect, [effect]);

  useEffect(() => {
    const subscription = vm.observeAppFocus$().subscribe(focus => {
      stableEffect(focus);
    });

    return () => subscription.unsubscribe();
  }, [vm, stableEffect]);
};

MobX: Estado Reativo que Simplifica Sua Vida

O MobX é o motor que faz nossa arquitetura MVVM brilhar. Aqui estão os conceitos essenciais:

Observable: Estados que “observam” mudanças

@observable phone: string = '';
@observable loading: boolean = false;

Action: Funções que modificam o estado

@action
setPhone(phone: string) {
  this.phone = phone;
}

Computed: Valores derivados do estado

@computed
get isFormValid(): boolean {
  return this.isPhoneValid && this.isTermsAccepted;
}

Por que MobX e não Redux?

  1. Menos boilerplate: Não precisa de actions creators, reducers, etc.
  2. Mais performático: Atualiza apenas componentes que realmente mudaram
  3. Mais intuitivo: Trabalha como JavaScript “normal”
  4. Debugging simpler: Estados são objetos simples

RxJS: Programação Reativa para Eventos Complexos

Para eventos assíncronos e streams de dados, usamos RxJS:

// Observa mudanças de foco da aplicação
observeAppFocus$(): Observable<AppFocus> {
  return this.focus$
    .asObservable()
    .pipe(
      filter(isNotNull), 
      distinctUntilChanged()
    );
}

// Escuta atualizações do app
private listenForAppUpdates(): Subscription {
  return appIsUpdated$()
    .pipe(first())
    .subscribe(() => {
      runInAction(() => {
        this.isAppUpdated = true;
      });
    });
}

Quando usar RxJS?

  • Eventos de tempo: Timers, debounce, throttle
  • Combinação de streams: Merge de múltiplas fontes de dados
  • Cancelamento: Requests que podem ser cancelados
  • Estados complexos: Máquinas de estado reativas

🎨 Layout da Aplicação: Provider Hierarchy

Nossa aplicação está estruturada em camadas de providers:

// app/_layout.tsx
const RootLayout = () => {
  return (
    <CoreProvider>           {/* Estado global da app */}
      <SynqProvider>         {/* WebSocket connections */}
        <QuteProvider>       {/* Design system */}
          <AuthProvider>     {/* Autenticação */}
            <PushProvider>   {/* Notificações */}
              <OrderProvider> {/* Pedidos */}
                <Slot />     {/* Páginas do app */}
              </OrderProvider>
            </PushProvider>
          </AuthProvider>
        </QuteProvider>
      </SynqProvider>
    </CoreProvider>
  );
};

Hierarchy Design Principles

  1. Core primeiro: Estados fundamentais ficam no topo
  2. Dependências claras: Cada provider depende apenas dos superiores
  3. Lazy loading: Providers carregam apenas quando necessário
  4. Error boundaries: Falhas isoladas não quebram toda a app
  5. Vantagens desta Arquitetura

✅ Para o Desenvolvedor

  • Tipagem forte: TypeScript previne bugs em tempo de compilação
  • Hot reload inteligente: MobX preserva estado durante desenvolvimento
  • Debugging avançado: MobX DevTools + RxJS DevTools
  • Testes simples: ViewModels são classes JavaScript puras

✅ Para o Negócio

  • Time to market: Desenvolvimento mais rápido com menos bugs
  • Escalabilidade: Arquitetura suporta crescimento da equipe
  • Manutenibilidade: Código organizado facilita mudanças
  • Performance: Updates otimizados do MobX

✅ Para a Equipe

  • Onboarding: Estrutura clara facilita entrada de novos devs
  • Colaboração: Padrões definidos reduzem conflitos
  • Conhecimento: Patterns amplamente usados na indústria

🎯 Próximos Passos

Na Parte II desta série, vamos mergulhar em:

  • Dependency Injection com Inversify: Como organizar dependências de forma testável
  • Repository Pattern: Abstraindo acesso a dados e APIs
  • Interceptors: Middleware para autenticação e logging
  • Testing Strategy: Como testar cada camada da aplicação
  • Performance Optimization: Técnicas para apps que escalam

Livros Indicados

Advanced React Native: Build Powerful Cross-Platform Mobile Apps with React Native 

Advanced React Native: Build Powerful Cross-Platform Mobile Apps with React Native 

React Native: Desenvolvimento de aplicativos mobile com React

React Native: Desenvolvimento de aplicativos mobile com React

Reflexão Final

Construir uma arquitetura sólida é como construir uma casa: você não vê a fundação, mas ela é o que sustenta tudo. Invista tempo no setup inicial e sua equipe agradecerá nos próximos anos.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *