<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Luma Montes</title>
    <description>The latest articles on Forem by Luma Montes (@lumamontes).</description>
    <link>https://forem.com/lumamontes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F754156%2F65fa5a91-b2f2-46c9-a101-c26318b72cd0.jpeg</url>
      <title>Forem: Luma Montes</title>
      <link>https://forem.com/lumamontes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/lumamontes"/>
    <language>en</language>
    <item>
      <title>Migração de dados entre serviços: estratégias, riscos e trade-offs</title>
      <dc:creator>Luma Montes</dc:creator>
      <pubDate>Sun, 18 Jan 2026 21:37:17 +0000</pubDate>
      <link>https://forem.com/lumamontes/migracao-de-dados-entre-servicos-estrategias-riscos-e-trade-offs-4p3c</link>
      <guid>https://forem.com/lumamontes/migracao-de-dados-entre-servicos-estrategias-riscos-e-trade-offs-4p3c</guid>
      <description>&lt;p&gt;&lt;strong&gt;Contexto&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Recentemente precisei migrar dezenas de milhares de registros de &lt;br&gt;
auditoria entre dois serviços durante uma task! Era minha primeira vez fazendo uma migração de dados, ainda mais dessa escala e aprendi bastante coisa, então decidi registrar neste artigo.&lt;/p&gt;

&lt;p&gt;Basicamente, uma migração de dados envolve pegar um conjunto de informações que estão armazenadas em uma determinada base (seja um banco de dados, uma planilha ou outro formato) e transformá-las para que possam ser consumidas corretamente por outro serviço, respeitando o modelo e as regras esperadas no destino.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftidf3075vbpf88htky3x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftidf3075vbpf88htky3x.png" alt=" " width="800" height="155"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As motivações para uma migração são diversas: Em alguns casos, estamos lidando com dados legados que precisam ser movidos para um novo serviço. Em outros, diferentes sistemas passam a compartilhar responsabilidades e precisam de uma interseção consistente de dados. Muitas vezes esse processo acontece de forma planejada, o que permite mais tempo para análise e execução. Mas também pode surgir de maneira urgente, pode ser demanda de um cliente, de um setor ou por uma necessidade operacional inesperada.&lt;/p&gt;

&lt;p&gt;A decisão de migrar pode partir tanto do time de produto quanto da engenharia. Ainda assim, é &lt;strong&gt;responsabilidade&lt;/strong&gt; do time de &lt;strong&gt;engenharia&lt;/strong&gt; avaliar e bater o martelo sobre a viabilidade técnica dessa migração! E essa viabilidade depende diretamente do estudo que a gente faz sobre os dados disponíveis.&lt;/p&gt;

&lt;p&gt;Por exemplo, quando a demanda vem de produto, normalmente existe um espaço maior para a engenharia investigar complexidade, riscos e custos. Mas nada disso se resolve apenas com um “dá pra migrar, galera! deixa que eu resolvo”. Antes de qualquer compromisso, é muuuuito importante analisar volumetria, estrutura e complexidade dos dados envolvidos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftijffltga9lazq3ip299.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftijffltga9lazq3ip299.png" alt=" " width="800" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Um exemplo claro: vale a pena a gente paralisar um ou dois devs por DUAS sprints para migrar 15 registros? Na maioria dos cenários, &lt;strong&gt;não&lt;/strong&gt;. O custo de engenharia pode ser alto demais para um impacto pequeno no produto.&lt;/p&gt;

&lt;p&gt;Claro que viabilidade não se resume apenas a números. O contexto do produto também importa. Que tipo de dado está sendo migrado? São dados simples ou recursivos? Existem dependências entre registros? Há estados intermediários, históricos ou regras de negócio acopladas a esses dados? Tudo isso influencia diretamente na decisão.&lt;/p&gt;

&lt;p&gt;Uma vez que a migração é considerada viável, fica mais claro o conjunto de problemas que precisam ser resolvidos. Em geral, eles se dividem em três grandes etapas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Extração&lt;/strong&gt;: como os dados serão puxados?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transformação&lt;/strong&gt;: como esses dados serão adaptados para o formato esperado?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Carregamento&lt;/strong&gt;: como os dados transformados serão enviados para o serviço de destino?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Foi nesse contexto que eu aprendi sobre &lt;strong&gt;ETL&lt;/strong&gt;, que é uma abordagem criada justamente para organizar e estruturar esse tipo de processo (Parabéns, você também aprendeu o que é ETL :))) &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Filolo2cpy7t1xqxes4fa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Filolo2cpy7t1xqxes4fa.png" alt=" " width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ainda assim, é importante reforçar: &lt;strong&gt;ETL&lt;/strong&gt; não é bala de prata. Em muitos casos, criar uma aplicação dedicada para migração pode ser uma complexidade desnecessária. Antes de qualquer implementação, é essencial estudar a viabilidade real da migração, entender o formato dos dados de origem, o esforço de transformação e o custo de manter essa solução também.&lt;/p&gt;

&lt;p&gt;De forma geral, ETLs fazem mais sentido quando a migração precisa ser executada mais de uma vez ou reaproveitada no futuro. Para migrações pontuais, uma solução mais simples pode ser suficiente e mais segura.&lt;/p&gt;

&lt;h2&gt;
  
  
  Estratégias
&lt;/h2&gt;

&lt;p&gt;Quando estou lidando com migrações menores, costumo optar por soluções simples. Em especial, gosto bastante de usar Jupyter Notebook, principalmente quando os dados de origem estão em planilhas ou em bases pequenas. Nesses cenários, não vejo muito sentido em construir uma aplicação inteira só para executar um processo pontual.&lt;/p&gt;

&lt;p&gt;Criar um notebook é relativamente simples: basta um arquivo com extensão .ipynb e um kernel configurado localmente. Dependendo do contexto, dá para usar Kotlin, Python, Deno, entre outras opções. A grande vantagem aqui é a rapidez para explorar os dados, testar transformações e iterar sem muitas dificuldades.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fppnmk045glscgqcx19so.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fppnmk045glscgqcx19so.png" alt=" " width="800" height="581"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Já para migrações mais complexas, minha preferência passa a ser criar uma aplicação local que roda via terminal — uma CLI simples, mas controlada. Esse tipo de abordagem permite mais previsibilidade, controle de execução e facilidade para lidar com grandes volumes de dados.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8w59uslh300rzxxop5e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8w59uslh300rzxxop5e.png" alt=" " width="649" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aqui, uma preocupação fundamental é ter uma estratégia de rollback. Nunca dá para assumir que a migração vai rodar perfeitamente de primeira. Sempre que possível, vale testar em ambiente de staging antes de executar em produção, além de alinhar muito bem o rollout com o time.&lt;/p&gt;

&lt;p&gt;A forma de carregar os dados também faz diferença. Em alguns casos, inserir diretamente no banco pode ser suficiente. Em outros, usar uma API ou até publicar eventos em fila é mais seguro, principalmente quando estamos lidando com grandes volumes e queremos processar tudo de forma assíncrona.&lt;/p&gt;

&lt;p&gt;No fim das contas, o formato do ETL importa menos do que o objetivo final. Ele pode ser um notebook, uma CLI ou até um script simples — desde que atenda às necessidades de extração, transformação e carregamento de forma segura e previsível.&lt;/p&gt;

&lt;h3&gt;
  
  
  Desafios práticos que você vai enfrentar
&lt;/h3&gt;

&lt;h5&gt;
  
  
  Dados faltando ou inconsistentes
&lt;/h5&gt;

&lt;p&gt;Em migrações reais, é muito comum encontrar dados incompletos, inconsistentes ou marcados como removidos (como casos de soft delete). Esses cenários precisam ser tratados explicitamente, seja ignorando registros, preenchendo valores padrão ou sinalizando dados desconhecidos.&lt;/p&gt;

&lt;h5&gt;
  
  
  Enriquecimento de dados
&lt;/h5&gt;

&lt;p&gt;Nem sempre todas as informações necessárias estão em um único lugar. Em alguns casos, é preciso bater em outros bancos de dados, outros serviços/apis pra buscar as informações que você precisa. É bom estar de olho nesse ponto desde o início, pois aumenta a complexidade&lt;/p&gt;




&lt;h3&gt;
  
  
  Trade-offs técnicos
&lt;/h3&gt;

&lt;p&gt;Abaixo estão alguns dos principais trade-offs que enfrentei: &lt;/p&gt;

&lt;h4&gt;
  
  
  Velocidade vs correção
&lt;/h4&gt;

&lt;p&gt;Quando a migração é urgente, você precisa decidir até onde aceitar inconsistências nos dados sem comprometer a entrega.&lt;/p&gt;

&lt;h4&gt;
  
  
  Jupyter Notebook vs CLI
&lt;/h4&gt;

&lt;p&gt;Para migrações pequenas, notebook resolve e acelera muito! Mas por experiência própria, ele pode crescer muito e dificultar a legibilidade e manutenção do script. Quando isso acontece, vale  mais a pena adotar uma CLI. &lt;/p&gt;

&lt;h3&gt;
  
  
  Migrar tudo vs migrar só o essencial
&lt;/h3&gt;

&lt;p&gt;Nem todo dado merece ser migrado, é muito importante alinhar com o time de produto quais dados serão preservados e quais dados podemos aceitar como "perdidos", de forma consciente.&lt;/p&gt;

&lt;h4&gt;
  
  
  Processar tudo de uma vez vs em lotes
&lt;/h4&gt;

&lt;p&gt;Por experiência própria, recomendo ir processando os registros em batches e ir verificando após cada uma se os dados foram da forma esperada. Isso é muito melhor do que ter que processar tudo de uma vez e precisar reprocessar por qualquer errinho nos tratamentos de dados. &lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusão
&lt;/h3&gt;

&lt;p&gt;Se ninguém percebeu que a migração de dados aconteceu em produção, provavelmente foi um bom sinal. No fim, tudo se resume a contexto, equilíbrio e trade-offs — e a manter o time alinhado sobre o que é possível entregar.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>data</category>
      <category>database</category>
    </item>
    <item>
      <title>Usando Guard/Wrapper components como alternativa a condições ternárias no React</title>
      <dc:creator>Luma Montes</dc:creator>
      <pubDate>Mon, 18 Aug 2025 02:35:02 +0000</pubDate>
      <link>https://forem.com/pupunhacode/usando-guardwrapper-components-como-alternativa-a-condicoes-ternarias-no-react-1ch8</link>
      <guid>https://forem.com/pupunhacode/usando-guardwrapper-components-como-alternativa-a-condicoes-ternarias-no-react-1ch8</guid>
      <description>&lt;p&gt;Esses dias me deparei com o seguinte código (eu mesma tinha feito ele no meio da madrugada) mais ou menos assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;isPaid&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex-1 flex flex-col xl:flex-row max-w-7xl mx-auto w-full p-4 sm:p-6 gap-6 xl:gap-8"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex-1 flex flex-col gap-6"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-lg font-semibold"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Pagamento já realizado&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-sm text-gray-500"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Obrigado por sua compra!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"outline"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Ver comprovante
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isPixModalOpen&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;pix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PixModal&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex-1 flex flex-col xl:flex-row max-w-7xl mx-auto w-full p-4 sm:p-6 gap-6 xl:gap-8"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex-1 flex flex-col gap-6"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PaymentMethodSelector&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PaymentDetails&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SecurityInfo&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;OrderSummary&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nada de errado até então... um pouco feio, mas é a vida né?&lt;/p&gt;

&lt;p&gt;Porém mais um pouco embaixo no código, &lt;strong&gt;novamente&lt;/strong&gt; precisei usar essa condicional:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;isPaid&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Conteúdo jsx gigantudo aqui quando pago&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; 
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Conteúdo jsx gigantudo quando não pago&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depois ainda usei mais algumas vezes, até me dar conta que tava ficando um pouquito feio de ler, por ser ternários com condições muuuito grandes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Melhorando o código
&lt;/h2&gt;

&lt;p&gt;Pensando nisso e inspirada pelo hook que já vem por padrão no inertia js (WhenVisible), podemos criar um componente que vai encapsular nossa regra de negócio!&lt;/p&gt;

&lt;p&gt;Por exemplo:&lt;/p&gt;

&lt;h2&gt;
  
  
  A versão genérica
&lt;/h2&gt;

&lt;p&gt;Podemos começar criando um componente bem simples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;WhenVisible&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;isVisible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;isVisible&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Antes:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isPaid&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Conteúdo do pagamento realizado&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Formulário de pagamento&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Depois:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;WhenVisible&lt;/span&gt; &lt;span class="na"&gt;isVisible&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isPaid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Conteúdo do pagamento realizado&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;WhenVisible&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;WhenVisible&lt;/span&gt; &lt;span class="na"&gt;isVisible&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isPaid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Formulário de pagamento&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;WhenVisible&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Versão menos genérica (e mais declarativa)
&lt;/h2&gt;

&lt;p&gt;Também podemos criar componentes ainda mais específicos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;WhenPaid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Conteúdo do pagamento realizado&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;WhenPaid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;WhenNotPaid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Formulário de pagamento&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;WhenNotPaid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  A implementação:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;WhenPaid&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isPaid&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;grab&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// função que pega as infos da página&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;isPaid&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;WhenNotPaid&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isPaid&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;grab&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isPaid&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pontos Positivos
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Legibilidade:&lt;/strong&gt; O código fica bem legível!!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Menos aninhamento:&lt;/strong&gt; É bem chatinho quando a gente precisa ficar se batendo pra fechar parênteses e chaves de um ternário gigantudo&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Reutilização:&lt;/strong&gt; Esses componentes podem ser usados em &lt;strong&gt;qualquer lugar&lt;/strong&gt; da aplicação&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Testabilidade:&lt;/strong&gt; Cada estado fica isolado e mais fácil de testar&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Manutenibilidade:&lt;/strong&gt; Mudança na lógica? Mexemos só no wrapper component que está em volta, não vai precisar alterar a mesma condição em vários lugares do seu código (tops)&lt;/p&gt;

&lt;h2&gt;
  
  
  Conditional Wrappers e outras arquiteturas
&lt;/h2&gt;

&lt;p&gt;Também existem várias outras formas de usar essa arquitetura para refatorar código e evitar duplicação:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Conditional Wrappers
&lt;/h3&gt;

&lt;p&gt;Sabe aquele código que só aplica um wrapper em certas condições? e aí você acaba repetindo o mesmo código em vários lugares só por causa do wrapper?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Antes &lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;shouldWrap&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"my-wrapper"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"my-wrapper"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Depois &lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ConditionalWrapper&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Wrapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;condition&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Wrapper&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Wrapper&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ConditionalWrapper&lt;/span&gt; &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;shouldWrap&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"my-wrapper"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ConditionalWrapper&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Role-Based Components
&lt;/h3&gt;

&lt;p&gt;Também vejo esse cara sendo usado bastante na parte de permissionamento, quando temos alguns tipos diferentes de permissão para o usuário, e dependendo da permissão dele, mostramos conteúdos diferentes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;WhenAdmin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAuth&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;WhenLoggedIn&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isAuthenticated&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAuth&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;isAuthenticated&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Uso super limpo&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;WhenLoggedIn&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserDashboard&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;WhenLoggedIn&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;WhenAdmin&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AdminPanel&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;WhenAdmin&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Feature Flag Components
&lt;/h3&gt;

&lt;p&gt;Para quando você tem features que só devem ser exibidas se estiverem ativas, como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;WhenFeatureEnabled&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isEnabled&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFeatureFlags&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Se isso aqui mudar, iremos alterar de uma vez em vários lugares&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;isEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;WhenFeatureEnabled&lt;/span&gt; &lt;span class="na"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"new-checkout"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NewCheckoutFlow&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;WhenFeatureEnabled&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;WhenFeatureEnabled&lt;/span&gt; &lt;span class="na"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"beta-features"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BetaFeaturesList&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;WhenFeatureEnabled&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Quando usar (e quando NÃO usar)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use wrapper components quando:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Você tem a &lt;strong&gt;mesma condicional repetida&lt;/strong&gt; várias vezes&lt;/li&gt;
&lt;li&gt;A condicional é &lt;strong&gt;complexa&lt;/strong&gt; (múltiplas condições)&lt;/li&gt;
&lt;li&gt;Você quer &lt;strong&gt;encapsular lógica&lt;/strong&gt; de negócio&lt;/li&gt;
&lt;li&gt;O código fica mais &lt;strong&gt;legível&lt;/strong&gt; e &lt;strong&gt;autodocumentado&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Continue tranquilamente com ternários quando:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;É uma condicional &lt;strong&gt;simples&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;O ternário deixa o código &lt;strong&gt;mais direto&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Você não vai reutilizar essa lógica&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O simples já funciona&lt;/strong&gt; - não precisa complicar!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Exemplo onde ternário é perfeito:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Super direto e claro !&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Spinner&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Content&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Usuário Anônimo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Badge&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Badge&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dicas práticas para implementação!
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Comece simples
&lt;/h3&gt;

&lt;p&gt;Comece com o &lt;code&gt;WhenVisible&lt;/code&gt; genérico e só evolua &lt;strong&gt;se&lt;/strong&gt; realmente precisar. Muitas vezes a versão genérica já resolve vários casos!&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Questione-se sempre: "Isso realmente está melhor?"
&lt;/h3&gt;

&lt;p&gt;Antes de refatorar, se pergunte:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O código ficou mais legível?&lt;/li&gt;
&lt;li&gt;A equipe vai entender facilmente?&lt;/li&gt;
&lt;li&gt;Estou resolvendo um problema real ou criando complexidade desnecessária?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ah, e como toda mudança de "padrão", comunique com a sua equipe, pegue uns pitacos e opiniões pra ver se realmente faz sentido no seu caso de uso :)&lt;/p&gt;

&lt;p&gt;Eu particularmente achei bem legal principalmente em casos de ternários grandes e difíceis de ler, além dos que são muito aninhados ou ternários com condições repetidas em vários lugares!&lt;/p&gt;

</description>
      <category>react</category>
      <category>braziliandevs</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>O que eu aprendi liderando tecnicamente a criação de um aplicativo de comunicação escolar</title>
      <dc:creator>Luma Montes</dc:creator>
      <pubDate>Sat, 09 Aug 2025 22:06:56 +0000</pubDate>
      <link>https://forem.com/lumamontes/o-que-eu-aprendi-liderando-tecnicamente-a-criacao-de-um-aplicativo-de-comunicacao-escolar-1agl</link>
      <guid>https://forem.com/lumamontes/o-que-eu-aprendi-liderando-tecnicamente-a-criacao-de-um-aplicativo-de-comunicacao-escolar-1agl</guid>
      <description>&lt;h2&gt;
  
  
  1. Como decidir a stack inicial de um produto mobile?
&lt;/h2&gt;

&lt;p&gt;Valide sempre com a sua equipe a escolha de stack e ferramentas!&lt;/p&gt;

&lt;p&gt;No nosso caso, optamos por React Native por conta de alguns motivos como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Equipe reduzida alocada no projeto&lt;/li&gt;
&lt;li&gt;Equipe com experiência prévia em React (e não em desenvolvimento nativo ou outras tecnologias mobile)&lt;/li&gt;
&lt;li&gt;Facilidade de compartilhamento de código com a versão web do produto (que é em React)&lt;/li&gt;
&lt;li&gt;Prazo de entrega que exigia agilidade no desenvolvimento.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Se for React Native, use TypeScript!
&lt;/h2&gt;

&lt;p&gt;Como uma dev que precisou migrar nos 45 do segundo tempo o projeto pra TypeScript, eu digo: faça com TypeScript desde o início. Por favor (!!!)&lt;/p&gt;

&lt;p&gt;Vai facilitar muito a manutenção do seu app, reduzir bugs bobos e tornar o onboarding de novos devs muito mais tranquilo. O que parece "trabalho extra" no começo vira economia de tempo gigante depois.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffk4vledc0mfnq3f1v6pg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffk4vledc0mfnq3f1v6pg.png" alt="Print da migração para typescript" width="319" height="132"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;no meio da jornada..já estava alucinando&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmn0w7a578hsyd2jt393m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmn0w7a578hsyd2jt393m.png" alt="Print da migração para typescript" width="341" height="135"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;conseguimos!!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Defina um padrão de código e arquitetura de pastas
&lt;/h2&gt;

&lt;p&gt;Isso foi algo um pouco difícil no começo, pois eu mesma tinha pouca experiência em desenvolvimento mobile, e precisei estudar bastante pra entender qual seria o melhor fluxo pra nossa realidade.&lt;/p&gt;

&lt;p&gt;O mais importante é definir um padrão de código claro, que faça sentido pro seu projeto, e ser consistente com ele. Não precisa ser perfeito desde o início, não tem nenhum problema em evoluir conforme a equipe aprende também! Seja receptivo a sugestões e mudanças.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Faça uma "entrega de bastão" com outras pessoas do time
&lt;/h2&gt;

&lt;p&gt;Depois de um tempo do começo do projeto, percebi que como muita coisa do app estava sendo desenvolvida somente por mim, isso gerava um sentimento de que "eu" era a única pessoa responsável pelo projeto que poderia resolver alguns pepinos depois da primeira entrega. É o famoso Bus Factor, evite ele a todo custo!&lt;/p&gt;

&lt;p&gt;Por isso, organizei um momento onde reuni a galera, compartilhei a tela e mostrei na prática como o projeto funcionava, junto com uma documentação. O objetivo era quebrar essa barreira e incentivar todo mundo a se sentir à vontade pra mexer no app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5bxmnem87yffzzex1kvv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5bxmnem87yffzzex1kvv.png" alt="Print da reunião de entrega de bastão" width="744" height="311"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Minha cartolina&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Crie uma documentação bacana
&lt;/h2&gt;

&lt;p&gt;Mais uma coisa que pequei no começo do projeto (até devido ao prazo de entrega) foi a documentação. Isso acabou gerando problemas quando outros devs foram me ajudar no projeto: pela falta de documentação, ficou difícil entender algumas decisões que foram tomadas e como o código estava estruturado também, além de alguns processos que estavam só na minha cabeça. Basicamente eu me tornei a documentação, o que não é muito legal.&lt;/p&gt;

&lt;p&gt;Como viver é aprender, hoje já tenho mais cuidado com a documentação e procuro sempre deixá-la atualizada! Recomendo fortemente que você faça o mesmo desde o início.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbxks4mad6n59krnwqgoa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbxks4mad6n59krnwqgoa.png" alt="Print sobre a minha documetação do projeto" width="397" height="308"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Um pouco da documentação que criei&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Recomendação: utilize Expo
&lt;/h2&gt;

&lt;p&gt;Eu sempre tento ir por uma abordagem pragmática das coisas (não sei se é por que sou dev PHP haha), mas considerando nosso contexto (equipe reduzida de 1-2 devs, prazo de entrega bem curto, aplicativo sem funcionalidades super complexas) foi muito fácil a decisão de usar o Expo.&lt;/p&gt;

&lt;p&gt;Ele atende super bem e a parte do EAS (que é a cloud deles) também vai quebrar um galho caso existam pessoas no seu time com pouca experiência em desenvolvimento mobile ou sem ambiente configurado.&lt;/p&gt;

&lt;p&gt;E agora, com os Expo Modules, cada vez mais é possível ter liberdade pra mexer com código nativo quando necessário também!&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Fique de olho nas novas tecnologias e ferramentas
&lt;/h2&gt;

&lt;p&gt;Algo muito importante é a melhoria contínua. O ecossistema React/React Native é bem dinâmico e tá sempre lançando novidades.&lt;/p&gt;

&lt;p&gt;Fique atento às atualizações, tanto pra ver algo que você pode melhorar na sua aplicação quanto pra identificar algo que não esteja mais funcionando bem e que você pode remover ou substituir.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reflexão final
&lt;/h2&gt;

&lt;p&gt;Tooodo esse processo me ensinou que as decisões técnicas precisam sempre considerar o contexto da equipe e do negócio. O que funciona pra um projeto pode não funcionar pra outro, e tudo bem! O importante é aprender, adaptar e compartilhar o conhecimento com a galera.&lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>mobile</category>
      <category>reactnative</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Construindo Apps Local-First com Legend State no React Native</title>
      <dc:creator>Luma Montes</dc:creator>
      <pubDate>Fri, 16 May 2025 09:58:25 +0000</pubDate>
      <link>https://forem.com/lumamontes/construindo-apps-local-first-com-legend-state-no-react-native-11nf</link>
      <guid>https://forem.com/lumamontes/construindo-apps-local-first-com-legend-state-no-react-native-11nf</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;Se você quiser ir direto para o código, esse &lt;a href="https://github.com/lumamontes/local-first-legend-state" rel="noopener noreferrer"&gt;repositório aqui&lt;/a&gt; tá contendo uma API e um app com Expo que implementam tudo que falei nesse artigo:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Local-First é um conceito super popular no desenvolvimento de aplicações modernas que oferece uma ótima experiência para o usuário. Na prática, é um conceito bem direto: todas as ações são "cacheadas" localmente antes de serem sincronizadas com o backend, permitindo que o app funcione mesmo offline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Os desafios do Local-First
&lt;/h2&gt;

&lt;p&gt;Implementar traz alguns desafios bem específicos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Como monitorar o status de conectividade do usuário que fica mudando o tempo todo?&lt;/li&gt;
&lt;li&gt;Como disparar a sincronização com o backend quando voltar online?&lt;/li&gt;
&lt;li&gt;Vou precisar fazer todo esse gerenciamento do zero no meu projeto?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Felizmente, existem diversas soluções que facilitam a implementação do Local-First em diferentes aplicações, mas neste artigo eu vou falar um pouquinho sobre uma lib mais recente e bem legal que oferece uma solução elegante para esse problema: &lt;strong&gt;Legend State&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que Legend State?
&lt;/h2&gt;

&lt;p&gt;O Legend State é &lt;strong&gt;extremamente rápido&lt;/strong&gt; (&lt;a href="https://legendapp.com/open-source/state/v3/intro/introduction/#2-%EF%B8%8F-the-fastest-react-state-library" rel="noopener noreferrer"&gt;dá uma olhada nos benchmarks&lt;/a&gt;) e se trata de uma lib de gerenciamento de estado local e remoto com um poderoso sistema de sincronização que funciona com qualquer backend.&lt;/p&gt;

&lt;p&gt;Maaaas para ser tão rápido, o Legend State possui um conceito de "reatividade" um pouco diferente do React tradicional. Não vou entrar em muitos detalhes aqui, mas recomendo dar uma olhada na documentação oficial sobre, existe alguns conceitos novos que precisamos aprender para usar a lib da melhor forma.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://legendapp.com/open-source/state/v3/intro/introduction/" rel="noopener noreferrer"&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://legendapp.com/open-source/state/v3/concepts/fine-grained/" rel="noopener noreferrer"&gt;Fine Grained Reactivity&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Um ponto que também vale a pena mencionar é que versão recomendada  atualmente pelo Legend State ainda está em beta, mas bem próximo de um lançamento oficial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vamos ao código!
&lt;/h2&gt;

&lt;p&gt;Vamos criar um app de posts que funciona offline-first, com sincronização automática quando online. Primeiro, vamos configurar nossa store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// store/posts.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;observable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@legendapp/state&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ObservablePersistLocalStorage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@legendapp/state/persist-plugins/local-storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ObservablePersistMMKV&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@legendapp/state/persist-plugins/mmkv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;syncedCrud&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@legendapp/state/sync-plugins/crud&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Platform&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CreatePostInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Pick&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CreatePostOutput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getPosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/posts`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createPost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CreatePostInput&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/posts`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updatePost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/posts/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PUT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deletePost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/posts/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DELETE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;postStore$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;syncedCrud&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CreatePostInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CreatePostInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;array&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;array&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;getPosts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Aqui usamos list pois nosso endpoint retorna // um conjunto de dados. caso retornasse somente um dado, usariamos // get e não list&lt;/span&gt;
  &lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;createPost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;update&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;updatePost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;deletePost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;persist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Platform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OS&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;web&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;ObservablePersistLocalStorage&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ObservablePersistMMKV&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;onSaved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//Quando o post é salvo no backend, recebemos a resposta aqui&lt;/span&gt;
    &lt;span class="c1"&gt;//E podemos atualizar o post no store de acordo com os dados do post salvo no backend, caso quisermos&lt;/span&gt;
    &lt;span class="c1"&gt;//Por exemplo, se quisermos atualizar o post com o id do post salvo no backend etc&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;saved&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;retry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;infinite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Continua tentando em caso de erro&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;syncMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fieldUpdatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;updatedAt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fieldCreatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;createdAt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perceba que usamos o &lt;code&gt;syncedCrud&lt;/code&gt;, um plugin pronto criado pelo Legend State que pode se conectar com qualquer backend. Com ele, basta a gente definir quais funções se conectam aos endpoints para ter toda a lógica de sincronização pronta (bem show).&lt;/p&gt;

&lt;p&gt;O código acima já configura:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A tipagem&lt;/li&gt;
&lt;li&gt;Os métodos CRUD que se comunicam com a API. Então o list seria o endpoint getAll do meu CRUD, e assim por diante&lt;/li&gt;
&lt;li&gt;A persistência de dados multiplataforma (LocalStorage na web, MMKV no mobile)&lt;/li&gt;
&lt;li&gt;O modo de sincronização automática&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Implementando o componente principal
&lt;/h2&gt;

&lt;p&gt;O componente principal do app mostra como usar o store e lidar com conectividade:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;View&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ScrollView&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;use$&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@legendapp/state/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useObservable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@legendapp/state/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;NetInfo&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@react-native-community/netinfo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;syncState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@legendapp/state&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;postStore$&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;store/posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;types/post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CreatePostForm&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/CreatePostForm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PostCard&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/PostCard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;//Adicionamos o observer para esse componente ficar verificando as mudanças &lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;connectivityStatus$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useObservable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;checking&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;postStore$&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;syncState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;postStore$&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isLoaded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoaded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unsubscribe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;NetInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;connectivityStatus$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isConnected&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;online&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex-1 bg-gray-50&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ScrollView&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex-1 px-4 pt-12&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mb-6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text-3xl font-bold text-gray-900&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Posts&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Text&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/View&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ConnectionStatus&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;connectivityStatus$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isError&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mb-6 rounded-lg bg-red-100 p-4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text-sm font-medium text-red-800&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Text&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/View&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;)}&lt;/span&gt;

        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isLoaded&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mb-6 rounded-lg bg-blue-100 p-4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text-sm font-medium text-blue-800&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Carregando&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Text&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/View&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;)}&lt;/span&gt;

        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PostCard&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;))}&lt;/span&gt;

        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mb-6 rounded-lg bg-gray-100 p-4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text-sm font-medium text-gray-800&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Nenhum&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="nx"&gt;encontrado&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Text&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/View&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;)}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ScrollView&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/View&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O componente acima:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Monitora o status de conectividade com o NetInfo&lt;/li&gt;
&lt;li&gt;Exibe um indicador visual para informar o usuário se está online ou offline&lt;/li&gt;
&lt;li&gt;Mostra estados de loading e erro conforme necessário&lt;/li&gt;
&lt;li&gt;Renderiza a lista de posts, já usando nossa store!&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  E agora para criar, atualizar e deletar os registros?
&lt;/h2&gt;

&lt;p&gt;Basta chamarmos a nossa store e manipularmos diretamente o nosso array: dando um push para criar, um set para atualizar e um delete para deletar.&lt;/p&gt;

&lt;p&gt;Por exemplo, o código no componente de card do post ficaria assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PostCard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;post&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;postId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleUpdate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;postStore$&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;postId&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;postStore$&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;postId&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;//Aqui automaticamente será chamado o endpoint de PUT&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleDelete&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;postStore$&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;postId&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;//Automaticamente sera chamado o endpoint de delete que configuramos&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;resto&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="nx"&gt;código&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E o código no componente de criação do post:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CreatePostForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setContent&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;randomId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;//Adiciona um id aleatório para o post, para salvar no local (e depois salvar no backend)&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;randomId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Lumix&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="nx"&gt;postStore$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//Aqui adicionamos na nossa store, e automaticamente será chamado o endpoint POST&lt;/span&gt;
      &lt;span class="nf"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;resto&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="nx"&gt;código&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prontinho! Nosso CRUD está pronto, com sincronização de dados offline que se conecta automaticamente com nosso backend ao mudar o status de conectividade do usuário :)&lt;/p&gt;

&lt;p&gt;Conseguimos implementar:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Persistência Cross-Platform&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web: LocalStorage&lt;/li&gt;
&lt;li&gt;Mobile: MMKV&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Sincronização Automática&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mudanças são salvas localmente primeiro&lt;/li&gt;
&lt;li&gt;Sincronização automática quando online&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;UI Responsiva&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Feedback imediato para o usuário&lt;/li&gt;
&lt;li&gt;Indicador de status de conexão&lt;/li&gt;
&lt;li&gt;Loading e error states&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;CRUD Completo&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create: Cria posts mesmo offline&lt;/li&gt;
&lt;li&gt;Read: Lista posts do cache local&lt;/li&gt;
&lt;li&gt;Update: Atualiza posts com sync automático&lt;/li&gt;
&lt;li&gt;Delete: Remove posts com sync quando online&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Menção honrosa: Hook onSaved
&lt;/h2&gt;

&lt;p&gt;Um recurso interessante do &lt;code&gt;syncedCrud&lt;/code&gt; é o hook &lt;code&gt;onSaved&lt;/code&gt;, que nos permite receber e processar a resposta do backend após uma operação ser sincronizada. No nosso exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;onSaved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//Quando o post é salvo no backend, recebemos a resposta aqui&lt;/span&gt;
  &lt;span class="c1"&gt;//E podemos atualizar o post no store de acordo com os dados do post salvo no backend&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;saved&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso é útil para casos onde o backend pode adicionar informações extras ao nosso objeto (como IDs gerados pelo banco, timestamps atualizados, etc).&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Com o Legend State, implementamos um app Local-First robusto com poucas linhas de código. A biblioteca cuida de toda a complexidade de sincronização, persistência e gerenciamento de estado, adiantando bastante o tempo de desenvolvimento.&lt;/p&gt;

&lt;p&gt;Recursos úteis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/lumamontes/local-first-legend-state" rel="noopener noreferrer"&gt;Repositório do github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://legendapp.com/open-source/state/" rel="noopener noreferrer"&gt;Legend State Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://legendapp.com/open-source/state/v3/sync/persist-sync/" rel="noopener noreferrer"&gt;Sync Plugins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://legendapp.com/open-source/state/v3/sync/crud/" rel="noopener noreferrer"&gt;CRUD Plugin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>reactnative</category>
      <category>node</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Construindo um monolito moderno com Inertia.js</title>
      <dc:creator>Luma Montes</dc:creator>
      <pubDate>Fri, 03 Jan 2025 20:31:56 +0000</pubDate>
      <link>https://forem.com/proesc/construindo-um-monolito-moderno-com-inertiajs-1j1k</link>
      <guid>https://forem.com/proesc/construindo-um-monolito-moderno-com-inertiajs-1j1k</guid>
      <description>&lt;p&gt;Recentemente tive uma experiência com Inertia Js em um projeto, e fiquei impressionada com a facilidade que foi o desenvolvimento! Neste artigo, vou falar um pouquinho sobre como o Inertia funciona e seus benefícios.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é o Inertia.js?
&lt;/h2&gt;

&lt;p&gt;O Inertia JS é uma nova abordagem criada pra facilitar o desenvolvimento de monolitos modernos. Ele tem uma forte relação com o ecossistema Laravel, mas também pode ser usado em outros frameworks de backend.  Um projeto com Inertia.js é bem parecido com os projetos em PHP, a diferença é que o frontend agora é em React (ou Vue). O inertia.js atua fazendo a comunicação entre o seu frontend e seu backend, substituindo a necessidade por uma API, por exemplo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que usar o Inertia.js?
&lt;/h2&gt;

&lt;p&gt;Seu objetivo de negócio e o seu time são alguns dos pontos a levar em consideração! Em projetos onde os times de frontend e backend são separados ou há integração entre diferentes negócios ou empresas, faz sentido dividir o sistema em serviços ou projetos independentes.&lt;/p&gt;

&lt;p&gt;Em contrapartida, um só time com poucos desenvolvedores que precisariam ser multidisciplinares, trabalhando tanto no código frontend quando backend o tempo todo, fez bastante sentido em utilizar o inertia pra entregar o projeto sem grandes complexidades que os microserviços trazem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como funciona?
&lt;/h2&gt;

&lt;p&gt;O Inertia.js elimina a necessidade de uma API tradicional. Você pode enviar dados do backend diretamente para o frontend como parâmetros em uma resposta, e o frontend usa esses dados para renderizar componentes. Para realizar a instalação, você pode seguir os passos da documentação:&lt;a href="https://inertiajs.com/server-side-setup" rel="noopener noreferrer"&gt;https://inertiajs.com/server-side-setup&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aqui adicionei um exemplo simples:&lt;/p&gt;

&lt;p&gt;Definição de rota:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// web.php&lt;/span&gt;
&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/books'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;BooksController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'index'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Criação de lógica no controller:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;//BooksController.php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Http\Controllers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Book&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Inertia\Inertia&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BooksController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$books&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Inertia&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Books/Index'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'books'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$books&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Renderização da sua view usando React e Typescript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// resources/js/Pages/Books/Index.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;usePage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@inertiajs/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;BooksIndex&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;books&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;usePage&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;books&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;book&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="p"&gt;))}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E pronto! Esse é um exemplo simples do funcionamento do inertia, quem já vem do desenvolvimento em PHP percebe que é bem parecido com as blades do PHP (tirando o fato de ser React/Vue).&lt;/p&gt;

&lt;p&gt;Nesse exemplo acima, o hook &lt;code&gt;usePage&lt;/code&gt; do Inertia é usado pra puxar as informações que mandamos como lá no controller. Além disso, alguns dos principais utilitários disponíveis são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;useRemember&lt;/strong&gt;: Armazena dados entre navegações de página.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WhenVisible&lt;/strong&gt;: Componente usado como forma de só carregar dados quando um elemento se torna vísivel na página&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deferred&lt;/strong&gt;: Permite você adie o carragamento de determinados nados da ágina até depois da renderização inicial, especialment usando em casos onde parte dos dados não são imediatamente necessárias no primeiro carregamento&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Link&lt;/strong&gt;: Componente usado para navegação, similar ao  do React Router&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Logicamente, tudo depende dos requisitos do seu projeto e do seu time. Mas o Inertia é uma ótima ferramenta que vem crescendo e se desenvolvendo cada vez mais no ecossistema laravel, uma ótima pedida pra projetos monolitos com PHP e com frameworks modernos como React/Vue para trazer uma melhor experiência para os usuários. A seguir o link da documentação, que foi base para este artigo, recomendo a leitura para conhecer mais sobre o Inertia:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://inertiajs.com/" rel="noopener noreferrer"&gt;https://inertiajs.com/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Introdução ao framework Astro</title>
      <dc:creator>Luma Montes</dc:creator>
      <pubDate>Sat, 18 May 2024 02:27:42 +0000</pubDate>
      <link>https://forem.com/lumamontes/introducao-ao-framework-astro-398j</link>
      <guid>https://forem.com/lumamontes/introducao-ao-framework-astro-398j</guid>
      <description>&lt;p&gt;Nos últimos tempos, ouvi falar bastante sobre o Astro! Um case recente que achei bem interessante foi a versão lite do site de noticías americano &lt;em&gt;NBC news&lt;/em&gt;, que foi criado usando esse framework com a finalidade de ser bem mais performático e acessível em situações de calamidade.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YFGVnVSo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://imgur.com/7cCHIbu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YFGVnVSo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://imgur.com/7cCHIbu.png" alt="NBC News" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Mas afinal, o que é Astro?
&lt;/h2&gt;

&lt;p&gt;Astro, segundo a própria documentação, é um framework web "tudo em um" para criação de websites rápidos, focados em &lt;strong&gt;&lt;em&gt;conteúdo&lt;/em&gt;&lt;/strong&gt;.&lt;br&gt;
Ele utiliza a estratégia de &lt;em&gt;MPA(Multi Page App)&lt;/em&gt;, em contraste com a estratégia de &lt;em&gt;SPA(Single Page App)&lt;/em&gt; utilizada por frameworks como Next, Vue, Svelte, etc. Isso significa que ele irá possuir múltiplas páginas HTML e dará preferência, sempre que possível, a rendereração de conteúdo no servidor, ao invés de renderizar no cliente, como é feito em SPAs. &lt;/p&gt;

&lt;p&gt;A estratégia MPA é uma abordagem tradicional e usada por diversas linguagens, como por exemplo o PHP. Mas diferente do PHP, onde é utilizado o PHP no servidor e Javascript no navegador, o Astro trás uma abordagem única onde o Javascript é utilizado tanto no servidor quando no navegador. &lt;/p&gt;

&lt;p&gt;Isso torna o seu site bem mais rápido e performático. Logo, sites que possuem bastante conteúdo estático como blogs, sites de notícias, portfólios, etc, são os principais candidatos a se beneficiar com o uso do Astro.&lt;/p&gt;

&lt;h2&gt;
  
  
  Porque Astro?
&lt;/h2&gt;

&lt;p&gt;O Astro possui uma boa experiência de desenvolvimento, com uma linguagem relativamente simples e conceitos bem famíliares. A ideia deles é que qualquer pessoa que tenha um pouco de contato com HTML, CSS e Javascript consiga criar um projeto rapidamente.&lt;/p&gt;

&lt;p&gt;Além de possuir uma API própria para criação de componentes utilizando arquivos &lt;code&gt;.astro&lt;/code&gt;, o framework oferece diversas integrações com outras ferramentas, como React, Vue, Svelte, Solid e mais. Isso significa que dentro de um componente estático &lt;code&gt;.astro&lt;/code&gt;`, voce pode importar um componente em React, por exemplo. Isso é bem interessante, pois permite que você utilize o Astro em conjunto com outras ferramentas, sem precisar se prender a uma única tecnologia, trazendo a superfície o conceito de UI agnóstica desse framework.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vHNdplCk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://imgur.com/I99EsDg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vHNdplCk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://imgur.com/I99EsDg.png" alt="React Astro code example" width="800" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No entanto, um dos grandes destaques realmente é a performance. Com o conceito de zero Javascript por padrão e renderização de conteúdo com preferência no servidor, utilizando a arquitetura MPA, o seu site será leve e rápido. Fazendo uma comparação direta do mesmo blog feito com Astro e com o Next.js por exemplo, foi identificado um carregamento 40% mais rápido e com 90% menos Javascript.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K-6_QkzI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://imgur.com/mive5NN.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K-6_QkzI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://imgur.com/mive5NN.png" alt="Alt text" width="800" height="954"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Outros principais conceitos que podemos destacar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sintaxe de componentes própria(&lt;code&gt;meucomponente.astro&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Roteamento baseado em arquivos&lt;/li&gt;
&lt;li&gt;Manipulação de assets, processo de build, bundling, otimizações, busca de dados e mais.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Por fim, possui uma boa documentação e uma comunidade bem ativa e em crescimento.&lt;/p&gt;

&lt;p&gt;Caso voce queira saber mais sobre o Astro, recomendo que voce leia a documentação oficial, que é bem completa e possui diversos exemplos e tutoriais, e serviu como base para esse post :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.astro.build/pt-br/getting-started/"&gt;https://docs.astro.build/pt-br/getting-started/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Por lá, também é possível encontrar diversos templates que podem ajudar a entender melhor o framework ou até mesmo já servir de base para o seu próximo projeto. ✨&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>astro</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Gerenciamento de estados de forma minimalista no React Native com Jotai</title>
      <dc:creator>Luma Montes</dc:creator>
      <pubDate>Sat, 09 Mar 2024 17:12:34 +0000</pubDate>
      <link>https://forem.com/lumamontes/gerenciamento-de-estados-de-forma-minimalista-no-react-native-com-jotai-5fle</link>
      <guid>https://forem.com/lumamontes/gerenciamento-de-estados-de-forma-minimalista-no-react-native-com-jotai-5fle</guid>
      <description>&lt;p&gt;Nesse artigo, vou falar sobre o Jotai, uma biblioteca de gerenciamento de estados globais para React. Vou explicar o que é, como instalar e como usar, com exemplos práticos.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é Jotai?
&lt;/h2&gt;

&lt;p&gt;Jotai é uma biblioteca de gerenciamento de estados globais para React, destacando-se pela simplicidade e facilidade de uso. Ela é capaz de escalar desde aplicações simples até aquelas com estados mais complexos, graças à sua flexibilidade e performance. Com apenas 2kb, a API principal é extremamente leve, contribuindo para a eficiência da biblioteca. A Jotai adota uma abordagem 'atômica' para o gerenciamento de estados globais.&lt;/p&gt;

&lt;p&gt;Nesse exemplo vou estar utilizando Jotai em React Native com Typescript, porém o Jotai é compatível com outros frameworks como Next.js, Gatsby, Remix e Waku.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalação
&lt;/h2&gt;

&lt;p&gt;Para instalar o Jotai, basta rodar o comando no seu terminal do seu projeto React Native:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;jotai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ou&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add jotai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ou&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add jotai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exemplo
&lt;/h2&gt;

&lt;p&gt;O Jotai tem uma estrutura definida por átomos, que são os estados. Pra qualquer estado ou variável global que você quiser criar, você vai criar um átomo.&lt;/p&gt;

&lt;p&gt;No meu exemplo, digamos que eu tenha um app financeiro e eu queira 2 estados globais, que vou precisar acessar em vários lugares do app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;um número inteiro que irá armazenar o saldo do usuário.&lt;/li&gt;
&lt;li&gt;um booleano que vai controlar se o saldo financeiro está visível ou não.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Logo, eu vou criar 2 átomos, um para cada estado que eu quero armazenar. Uma boa prática é criar um arquivo separado somente para a criação dos átomos, para que fique mais organizado. No meu exemplo, na raiz do projeto mesmo irei criar um arquivo chamado &lt;code&gt;Atoms.ts&lt;/code&gt; que vai conter todos os átomos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;atom&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jotai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;balanceAtom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isBalanceVisibleAtom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Conforme o exemplo acima, usei a função &lt;code&gt;atom&lt;/code&gt; do Jotai para criar um átomo que representa um estado global.&lt;/p&gt;

&lt;p&gt;Essa função &lt;code&gt;atom&lt;/code&gt; recebe um parâmetro que é o valor inicial do átomo, e dependendo do tipo desse valor, o Jotai já consegue inferir o tipo do átomo. &lt;/p&gt;

&lt;p&gt;Por exemplo, no meu caso, o átomo &lt;code&gt;isBalanceVisibleAtom&lt;/code&gt; é um booleano, então eu passei um &lt;code&gt;false&lt;/code&gt; como valor inicial. E o átomo &lt;code&gt;balanceAtom&lt;/code&gt; é um número, então eu passei 0 como valor inicial.&lt;/p&gt;

&lt;p&gt;E é isso! Agora eu posso chamar esses átomos em qualquer lugar do meu app, para visualizar e/ou alterar o valor dos mesmos utilizando o hook &lt;code&gt;useAtom&lt;/code&gt; do Jotai.&lt;/p&gt;

&lt;p&gt;Primeiro, vou criar um componente que irá exibir o saldo do usuário e um botão para adicionar um valor de 10 ao saldo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;View&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useAtom&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jotai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;balanceAtom&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/Atoms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Balance&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setBalance&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAtom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;balanceAtom&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Saldo: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Adicionar 10"&lt;/span&gt; &lt;span class="na"&gt;onPress&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setBalance&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; 
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Conforme o exemplo acima, utilizamos o hook &lt;code&gt;useAtom&lt;/code&gt; do Jotai, que irá retornar duas funções que são parecidas com o useState do React. A primeira função será o valor desse átomo, e a segunda é uma função pra atualizar o valor desse átomo.&lt;/p&gt;

&lt;p&gt;Nesse caso, quero exibir em tela o saldo do usuário, então no useAtom passei como parâmetro o &lt;code&gt;balanceAtom&lt;/code&gt; que é o átomo que defini para representar esse estado.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useAtom(balanceAtom);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E como retorno, eu recebo o valor do saldo e a função para atualizar o saldo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [balance, setBalance] = useAtom(balanceAtom);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, vamos criar um componente de header que irá exibir um botão para mostrar ou esconder o saldo do usuário.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useAtom&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jotai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isBalanceVisibleAtom&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/Atoms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;funcion&lt;/span&gt; &lt;span class="nc"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isBalanceVisible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsBalanceVisible&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAtom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isBalanceVisibleAtom&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Bem vindo!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Mostrar saldo"&lt;/span&gt; &lt;span class="na"&gt;onPress&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setIsBalanceVisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isBalanceVisible&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, posso atualizar o componente Balance para que ele só seja exibido se o saldo estiver visível.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;View&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useAtom&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jotai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;balanceAtom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isBalanceVisibleAtom&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/Atoms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Balance&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setBalance&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAtom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;balanceAtom&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isBalanceVisible&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAtom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isBalanceVisibleAtom&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Saldo: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isBalanceVisible&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;***&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Adicionar 10"&lt;/span&gt; &lt;span class="na"&gt;onPress&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setBalance&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dessa forma, o saldo só será exibido se o usuário clicar no botão "Mostrar saldo" do componente Header.&lt;/p&gt;

&lt;p&gt;E é isso! Agora eu tenho 2 estados globais que posso acessar e posso atualizar de qualquer lugar do meu app. E o melhor de tudo, o Jotai já cuida de atualizar todos os componentes que estão usando esses átomos, lidando por trás dos panos otimização, memorização, e re-renders desnecessários.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;o Jotai é uma biblioteca fantástica que simplifica muito o gerenciamento de estados do React. Além dos exemplos que mostrei, o Jotai tem várias outras funcionalidades que podem ser muito úteis, como um pacote responsável por fazer cache de átomos, fazer transições de estados, integração com outras ferramentas como React Query, e muito mais.&lt;/p&gt;

&lt;p&gt;Recomendo dar uma olhada na documentação oficial para ver mais detalhes e exemplos de uso: &lt;a href="https://jotai.org/"&gt;https://jotai.org/&lt;/a&gt; 🚀&lt;/p&gt;

</description>
      <category>react</category>
      <category>reactnative</category>
    </item>
    <item>
      <title>Fluxo de autenticação no React Native usando Expo Router</title>
      <dc:creator>Luma Montes</dc:creator>
      <pubDate>Sun, 18 Feb 2024 05:33:32 +0000</pubDate>
      <link>https://forem.com/proesc/fluxo-de-autenticacao-no-react-native-usando-expo-router-61h</link>
      <guid>https://forem.com/proesc/fluxo-de-autenticacao-no-react-native-usando-expo-router-61h</guid>
      <description>&lt;p&gt;Quem já trabalhou com rotas com Expo ou React Native, sabe que o React Navigation é a forma padrão de lidar com navegação! No entanto, conforme mais telas você vai criando no seu app, o código utilizado pode ficar bem grande, com processos manuais que precisam de muitas linhas de código para serem feitos. Logo, o time do Expo lançou uma novidade: Expo Router, uma alternativa ao React Navigation para roteamento e navegação com React Native. &lt;/p&gt;

&lt;p&gt;Esse post irá mostrar como criar um fluxo de autenticação com Expo Router no seu app React Native.&lt;/p&gt;

&lt;h2&gt;
  
  
  Índice
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
 Principais funcionalidades do Expo Router:
&lt;/li&gt;
&lt;li&gt;
 Pré-requisitos
&lt;/li&gt;
&lt;li&gt;
 Exemplo de código

&lt;ul&gt;
&lt;li&gt;  1 - Crie um contexto de autenticação
&lt;/li&gt;
&lt;li&gt;
 2 - Adicione o arquivo app/_layout.tsx
&lt;/li&gt;
&lt;li&gt;
 3 - Crie a tela de login
&lt;/li&gt;
&lt;li&gt;
 4 - Adicione a lógica de autenticação no arquivo app/(auth)/_layout.tsx
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

 Conclusão &lt;/li&gt;

&lt;/ul&gt;

&lt;h6&gt;
  
  
  generated with &lt;a href="https://summaryze-forem.vercel.app/" rel="noopener noreferrer"&gt;Summaryze Forem 🌱&lt;/a&gt;
&lt;/h6&gt;

&lt;h2&gt;
  
  
  Principais funcionalidades do Expo Router:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nativo&lt;/strong&gt;: Construído em cima do React Navigation, a navegação do Expo Router é nativa e otimizada.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compartilhável&lt;/strong&gt;: Toda tela do seu aplicativo é automaticamente configurada com deep linking. Tornando qualquer rota do seu aplicativo compartilhável com links, como por exemplo, um link de redirecionamento de uma notificação, não sendo necessário configurar manualmente quais telas são acessíveis por links.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Offline-first&lt;/strong&gt;: Os aplicativos são armazenados em cache e executados de forma offline first, com atualizações automáticas quando você publica uma nova versão.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O Expo Router trás um conceito de &lt;em&gt;file based routing&lt;/em&gt;, ou seja, as rotas da aplicação refletem a estrutura dos arquivos criados na pasta &lt;code&gt;/app&lt;/code&gt;. Parecido, por exemplo, com a estrutura do Next.js.&lt;/p&gt;

&lt;p&gt;Quando um arquivo é criado na pasta app, automaticamente se torna uma rota no app. Logo, diferentemente do React Navigation, todas as stacks (ou rotas) do seu app já ficam publicas e disponíveis para navegação! Além disso, as navegações para diferentes telas podem ser feitas usando um elemento &lt;code&gt;&amp;lt;Link href='/nome-da-rota'&lt;/code&gt;, por exemplo. bem parecido com o que fazemos na web. Você pode usar um router.replace('nome-da-rota') para definir globalmente o redirecionamento de rota, além de rotas dinâmicas, criação de grupos de rotas e muito mais. 🤯&lt;/p&gt;

&lt;h2&gt;
  
  
  Pré-requisitos
&lt;/h2&gt;

&lt;p&gt;Para o exemplo a seguir, você pode clonar o projeto para reproduzir o exemplo.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git clone git@github.com:lumamontes/expo-router-auth.git


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Instale as dependências do projeto:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx expo &lt;span class="nb"&gt;install&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;E rode o projeto:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx expo start


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Mas, caso queira criar um projeto do zero, você pode seguir os passos originais do &lt;a href="https://docs.expo.dev/router/installation/#quick-start" rel="noopener noreferrer"&gt;Expo Router&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exemplo de código
&lt;/h2&gt;

&lt;p&gt;Agora, vamos a um exemplo no código! Vamos implementar um fluxo de autenticação utilizando o Expo Router para navegação. Vamos analisar a estrutura do projeto:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgur.com%2FsEF6S5o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgur.com%2FsEF6S5o.png" alt="Pasted"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alguns pontos chaves para entender o Expo Router:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Todos os arquivos que estão na pasta &lt;code&gt;/app&lt;/code&gt; serão rotas (com exceção de arquivos "especiais", que irei comentar abaixo!)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;_layout.tsx&lt;/code&gt;: O expo router possibilita a criação de &lt;em&gt;Layout routes&lt;/em&gt;, elementos que são compartilhados entre diversas telas, como uma header. No caso do arquivo app/_layout.tsx, ele é um layout que será compartilhado entre todas as telas dentro da pasta &lt;code&gt;/app&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pastas &lt;code&gt;(auth)&lt;/code&gt; e &lt;code&gt;(tags)&lt;/code&gt;: são grupos de rotas do Expo Router, que são usados para organizar as rotas do app. Você pode adicionar quantos grupos quiser. Grupos também são bons para organizar seções do app. No exemplo a seguir, temos &lt;strong&gt;app/(auth)&lt;/strong&gt; que irá ter as telas para usuários autenticados. Um ponto interessante é que os grupos não afetam a url, ou seja, um arquivo localizado na pasta &lt;code&gt;app/(auth)/nome-do-arquivo.tsx&lt;/code&gt; não terá a url &lt;code&gt;app/(auth)/nome-do-arquivo&lt;/code&gt;, mas sim &lt;code&gt;app/nome-do-arquivo&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;ctx.tsx&lt;/code&gt;: é um contexto de autenticação, que irá centralizar algumas informações globais como a sessão do usuário, a função de logar e deslogar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;+not-found.tsx&lt;/code&gt;: é uma rota que será acessada quando nenhuma outra rota for encontrada.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Logo, o nosso app irá possui duas camadas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rotas para usuários autenticados (todo o conteúdo do grupo (auth))&lt;/li&gt;
&lt;li&gt;Rotas para usuários não autenticados (somente a tela de login)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para fazer essa separação entre a camada de usuários autenticados e não autenticados, é possível criar um contexto que vai definir essas regras de negócio:&lt;/p&gt;

&lt;h3&gt;
  
  
  1 - Crie um contexto de autenticação
&lt;/h3&gt;

&lt;p&gt;Esse contexto irá centralizar algumas informações e lógicas globais como a sessão do usuário, a função de signIn e signOut.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

iimport React from "react";
import { useStorageState } from "./useStorageState";

const AuthContext = React.createContext&amp;lt;{
  signIn: () =&amp;gt; void;
  signOut: () =&amp;gt; void;
  session?: string | null;
  isLoading: boolean;
}&amp;gt;({
  signIn: () =&amp;gt; null,
  signOut: () =&amp;gt; null,
  session: null,
  isLoading: false,
});

// This hook can be used to access the user info.
export function useSession() {
  const value = React.useContext(AuthContext);
  return value;
}

export function SessionProvider(props: React.PropsWithChildren) {
  const [[isLoading, session], setSession] = useStorageState("session");
  return (
    &amp;lt;AuthContext.Provider
      value={{
        signIn: () =&amp;gt; {
          // Add your login logic here
          // For example purposes, we'll just set a fake session in storage
          setSession("John Doe");
        },
        signOut: () =&amp;gt; {
          setSession(null);
        },
        session,
        isLoading,
      }}
    &amp;gt;
      {props.children}
    &amp;lt;/AuthContext.Provider&amp;gt;
  );
}



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;A função &lt;code&gt;signIn&lt;/code&gt; irá salvar a sessão do usuário, nesse caso, uma simples string 'John Doe', e a função &lt;code&gt;signOut&lt;/code&gt; irá remover a sessão alterando esse valor para null.&lt;/p&gt;

&lt;p&gt;Para finalidade de testes, a função signIn não irá ter nenhum tipo de validação, sempre que ela for chamada, o usuário será autenticado. No entanto, em um app real, você pode adicionar a lógica de login do seu app fazendo uma requisição para uma API, por exemplo.&lt;/p&gt;

&lt;p&gt;Um ponto importante é que iremos salvar essas informações de sessão do usuário no storage do dispositivo, para que o usuário não precise logar toda vez que abrir o app.&lt;/p&gt;

&lt;p&gt;Para isso, utilizaremos o hook &lt;code&gt;useStorageState&lt;/code&gt; que retornar um estado e uma função para alterar esse estado, salvar e recuperar as informações do storage do dispositivo utilizando a biblioteca &lt;code&gt;expo-secure-store&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Esse hook é composto por três funções:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A função &lt;code&gt;useAsyncState&lt;/code&gt; irá retornar um estado e uma função para alterar esse estado, mas com um estado inicial de loading, que será true, e o valor inicial, que será null.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import * as SecureStore from "expo-secure-store";
import * as React from "react";
import { Platform } from "react-native";

type UseStateHook&amp;lt;T&amp;gt; = [[boolean, T | null], (value: T | null) =&amp;gt; void];

function useAsyncState&amp;lt;T&amp;gt;(
  initialValue: [boolean, T | null] = [true, null]
): UseStateHook&amp;lt;T&amp;gt; {
  return React.useReducer(
    (
      state: [boolean, T | null],
      action: T | null = null
    ): [boolean, T | null] =&amp;gt; [false, action],
    initialValue
  ) as UseStateHook&amp;lt;T&amp;gt;;
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;setStorageItemAsync&lt;/code&gt;: que irá salvar ou deletar um item no storage do dispositivo, dependendo do valor passado.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

export async function setStorageItemAsync(key: string, value: string | null) {
  if (value == null) {
    await SecureStore.deleteItemAsync(key);
  } else {
    await SecureStore.setItemAsync(key, value);
  }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;useStorageState&lt;/code&gt;: que irá retornar um estado e uma função para alterar esse estado, salvando e recuperando as informações do storage do dispositivo utilizando a biblioteca &lt;code&gt;expo-secure-store&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

export function useStorageState(key: string): UseStateHook&amp;lt;string&amp;gt; {
  const [state, setState] = useAsyncState&amp;lt;string&amp;gt;();

  React.useEffect(() =&amp;gt; {
    SecureStore.getItemAsync(key).then((value) =&amp;gt; {
      setState(value);
    });
  }, [key]);

  const setValue = React.useCallback(
    (value: string | null) =&amp;gt; {
      setState(value);
      setStorageItemAsync(key, value);
    },
    [key]
  );

  return [state, setValue];
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Logo, se eu usar o hook dessa forma: useStorageState('session'), ele irá retornar: isLoading, session e setSession.&lt;/p&gt;

&lt;p&gt;Mas se eu usasse dessa forma: useStorageState('user'), ele irá retornar: isLoading, user e setUser, por exemplo.&lt;/p&gt;

&lt;p&gt;Podemos então entender que o useStorageState é um hook genérico que irá retornar um estado e uma função para alterar esse estado, salvando e recuperando as informações do storage do dispositivo utilizando a biblioteca &lt;code&gt;expo-secure-store&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2 - Adicione o arquivo app/_layout.tsx
&lt;/h3&gt;

&lt;p&gt;Esse arquivo é um layout que será compartilhado entre todas as telas do app. Nele, podemos:&lt;/p&gt;

&lt;h4&gt;
  
  
  - Definir a rota inicial do app
&lt;/h4&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

export const unstable_settings = {
  initialRouteName: "login",
};


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Essa simples linha de código irá garantir que a rota inicial do nosso app será sempre 'login', ou seja, o componente presente no arquivo de login.tsx!&lt;/p&gt;

&lt;h4&gt;
  
  
  - Adicionar o nosso contexto por volta de todo o seu app
&lt;/h4&gt;

&lt;p&gt;Ele irá apenas retornar o children, que será a stack do grupo &lt;code&gt;(auth)&lt;/code&gt; ou a tela de login, dependendo se o usuário está autenticado ou não. Para isso, usaremos o &lt;code&gt;&amp;lt;Slot&amp;gt;&lt;/code&gt; do Expo Router, que é um elemento que irá renderizar o "children" da rota atual:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { Slot } from "expo-router";
import { SessionProvider } from "./ctx";

export default function RootLayoutNav() {
  return (
    &amp;lt;SessionProvider&amp;gt;
      &amp;lt;Slot /&amp;gt;
    &amp;lt;/SessionProvider&amp;gt;
  );
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  3 - Crie a tela de login
&lt;/h3&gt;

&lt;p&gt;Na tela de login, que será o arquivo &lt;code&gt;app/login.tsx&lt;/code&gt;, você pode adicionar a lógica de login do seu app, como um formulário de email e senha. No nosso caso, vamos somente um botão que irá logar o usuário no app.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

export default function Login() {
  const { signIn } = useSession();
  const handleLogin = () =&amp;gt; {
    signIn();
    //Antes de navegar, tenha certeza de que o usuário está autenticado
    router.replace("/");
  };

  return (
    &amp;lt;View&amp;gt;
      &amp;lt;Button title="Login" onPress={handleLogin} /&amp;gt;
    &amp;lt;/View&amp;gt;
  );
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Isso irá redirecionar para &lt;code&gt;(auth)/\_layout.tsx&lt;/code&gt;!&lt;/p&gt;

&lt;h3&gt;
  
  
  4 - Adicione a lógica de autenticação no arquivo &lt;code&gt;app/(auth)/\_layout.tsx&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Esse arquivo é um layout que será compartilhado entre todas as telas do app no grupo (auth), ou seja, todas as telas que precisam de autenticação para serem acessadas. Nele, podemos adicionar a lógica de autenticação do app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Se o usuário não possuir sessão, redirecionar para a tela de login&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Caso o usuário tenha sessão, retornar a stack do grupo &lt;code&gt;(tabs)&lt;/code&gt;, que contém o restante das telas do app.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

const { session } = useSession();

if (!session) {
  return &amp;lt;Redirect href="/login" /&amp;gt;;
}

return (
  &amp;lt;Stack&amp;gt;
    &amp;lt;Stack.Screen name="(tabs)" options={{ headerShown: false }} /&amp;gt;

    &amp;lt;Stack.Screen name="modal" options={{ presentation: "modal" }} /&amp;gt;
  &amp;lt;/Stack&amp;gt;
);


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Assim, ao clicar para login e ser redirecionado com sucesso, o usuário irá ter acesso a tela &lt;code&gt;app/(auth)/(tabs)/index.tsx&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;E caso o usuário não esteja autenticado, ele será redirecionado para a tela de login, completando um fluxo básico de autenticação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Fazendo um comparativo com React Navigation, acredito que o Expo Router é bem acessível e fácil de entender, principalmente pra quem vem do desenvolvimento de frontend web.&lt;/p&gt;

&lt;p&gt;Onde no React Navigation, várias funcionalidades eram feitas de forma manual, como a criação das rotas, a configuração de deep linking, entre outras, esses processos super importantes são feitos já automaticamente pelo Expo Router, deixando o código bem mais limpo. Pelo fato de ser file based routing, a estrutura do projeto fica bem mais organizada, e a navegação entre telas é bem mais simples, com a utilização do elemento &lt;code&gt;&amp;lt;Link href='/nome-da-rota'&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;No geral, acredito que o Expo Router é uma ótima ferramenta para quem está começando a desenvolver apps com react native, ou para quem já tem experiência com react native e quer otimizar o tempo de desenvolvimento e manter uma navegação de fácil implementação. Estarei utilizando nos meus novos projetos com Expo 🚀&lt;/p&gt;

&lt;p&gt;Segue o link do projeto no github, caso queira testar o código:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/lumamontes/expo-router-auth" rel="noopener noreferrer"&gt;Expo Router Auth&lt;/a&gt;&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>expo</category>
      <category>mobile</category>
      <category>braziliandevs</category>
    </item>
  </channel>
</rss>
