🚀 Bem-vindo ao Lab! Aqui exploramos tecnologia e inovação.Siga-nos no google news.

Lab.

Refatorando um aplicativo React Native: decisões técnicas, performance e automação

Refatorando um aplicativo React Native: decisões técnicas, performance e automação

Recentemente, fiz uma atualização importante no meu aplicativo de nutrição, o Nutrilow. Nessa etapa, decidi parar por um tempo para estruturar melhor o que eu realmente queria construir — tanto como produto quanto como tecnologia.

O objetivo do Nutrilow sempre foi claro: auxiliar no controle de calorias e facilitar a conexão com nutricionistas. Porém, alcançar isso desenvolvendo no tempo livre, como hobby, não é simples. Conciliar tudo exige escolhas e foi justamente nesse momento que aproveitei para rever decisões e repensar a base do projeto.

Segurança, simplicidade e performance

Entre as melhorias, voltei a estudar com mais profundidade temas de segurança da informação, como pentest e boas práticas — algo que eu não revisava com calma há algum tempo.

Hoje, o ecossistema do Nutrilow não é multi-cloud. Isso é intencional. Não se trata de uma superempresa, então não faz sentido adicionar complexidade desnecessária. Em vez disso, foquei fortemente em performance, desde as queries no banco de dados até a otimização do aplicativo mobile. Vale destacar que tudo foi construído do zero.

Por que React Native?

A escolha do React Native em vez de Flutter foi natural. React é minha principal especialidade e gosto muito da forma como ele lida com o ecossistema como um todo. A separação entre o bundle nativo e os assets em JavaScript, somada ao domínio completo do que estou desenvolvendo, é algo que me motiva bastante.

Claro, surgiram desafios — e um dos principais foi otimização.

Segurança é um tema que levo muito a sério, então muitas vezes prefiro pecar pelo excesso de validações e chamadas do que deixar passar algo crítico. Porém, ao revisar o que havia sido feito, ficou claro que dava — e muito — para otimizar.

Foi aí que tudo começou a mudar.

Estado, chamadas repetidas e Zustand

Após o lançamento, voltei ao aplicativo com um olhar mais crítico e notei que estava fazendo muitas chamadas repetidas para os mesmos dados. Eu estava usando pouco um recurso que o React lida muito bem: estado.

Decidi então implementar um controle de estado mais robusto com Zustand, focando nos dados com maior repetição e realizando refetch apenas quando realmente necessário.

Design System e Atomic Design

Durante essa refatoração, percebi também que, no ritmo acelerado do lançamento, algumas coisas haviam fugido do padrão. Apesar de a separação entre componentes e páginas estar bem definida, o conjunto não estava consistente como eu gostaria.

Resolvi dar alguns passos para trás e refazer tudo, criando um Design System do zero, baseado em Atomic Design — uma abordagem com a qual já trabalhei bastante no ecossistema React.

Essa padronização levou cerca de duas semanas. Foi um processo de pegar algo pronto, reescrever, reavaliar e, principalmente, eliminar chamadas excessivas que poderiam virar cache.

Aqui entra outro ponto importante: quando bem utilizado, o React lida muito bem com otimizações como:

  • Memoização de componentes com useMemo
  • Cache de funções com useCallback

Após essas melhorias, a performance deu um salto enorme — mas ainda faltava algo.

Padronizando dados com React Query

Mesmo usando hooks e controlando estado com Zustand, percebi que o padrão das chamadas ainda não estava como eu queria. Foi então que pensei: por que não usar React Query?

Essa foi uma das melhorias-chave do projeto.

Com o React Query, consegui:

  • Isolar melhor as responsabilidades dos hooks
  • Padronizar o acesso aos dados
  • Monitorar estados de forma mais clara
  • Testar cenários de erro com mais precisão

Usei o React Native DevTools para simular falhas e validar fallbacks, o que trouxe muito mais confiança no comportamento do app em cenários reais.

Automação: CI/CD, versionamento e releases

Todo esse trabalho trouxe ganhos técnicos enormes, mas o fluxo de desenvolvimento ainda não estava tão amigável quanto eu queria.

Desde o início, já existiam processos automatizados de CI/CD — inicialmente com Fastlane e, depois, migrando essa responsabilidade para o Expo. A entrega na loja após testes beta já era automatizada.

Mesmo assim, algo ainda me incomodava: versionamento manual, commits repetitivos e ajustes que poderiam ser automatizados.

Foi então que veio a próxima melhoria: Semantic Commits + GitHub Actions.

Passei a usar semantic commits para:

  • Gerar automaticamente tags
  • Criar changelog
  • Atualizar a versão no package.json
  • Disparar o envio para o Expo

Simples, previsível e bonito de ver funcionando.

Próximos passos

Toda essa atualização foi focada apenas no mobile. Pretendo detalhar futuramente alguns pontos mais técnicos, como:

  • O Design System
  • Três bibliotecas internas que precisei criar durante o desenvolvimento
  • Melhorias realizadas no backend

Mas, por hoje, essa já é uma atualização grande — e necessária.

Construir software no tempo livre exige foco, escolhas conscientes e, principalmente, disposição para voltar atrás quando algo não faz mais sentido. Esse refactor foi exatamente isso.