<?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>DEV Community: Marcos Anjos</title>
    <description>The latest articles on DEV Community by Marcos Anjos (@devmarcosanjos).</description>
    <link>https://dev.to/devmarcosanjos</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%2F1840500%2Fda71375f-e6b3-4211-8e73-e1d92d57983e.png</url>
      <title>DEV Community: Marcos Anjos</title>
      <link>https://dev.to/devmarcosanjos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/devmarcosanjos"/>
    <language>en</language>
    <item>
      <title>Jetpack Compose fez sentido pra mim quando eu parei de comparar tudo com XML</title>
      <dc:creator>Marcos Anjos</dc:creator>
      <pubDate>Wed, 01 Apr 2026 01:48:48 +0000</pubDate>
      <link>https://dev.to/devmarcosanjos/jetpack-compose-fez-sentido-pra-mim-quando-eu-parei-de-comparar-tudo-com-xml-1faf</link>
      <guid>https://dev.to/devmarcosanjos/jetpack-compose-fez-sentido-pra-mim-quando-eu-parei-de-comparar-tudo-com-xml-1faf</guid>
      <description>&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%2Firzo5rwy3wi899qf55cq.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%2Firzo5rwy3wi899qf55cq.png" alt="Image JetpackCompose logo" width="480" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quando comecei a mexer com Jetpack Compose, tentei entender tudo com a cabeça do Android antigo. Eu ainda pensava em XML, &lt;code&gt;Activity&lt;/code&gt;, &lt;code&gt;Fragment&lt;/code&gt; e atualização manual de interface. Por isso, no começo, parecia que estava faltando alguma coisa: cadê o XML, os ids e o &lt;code&gt;findViewById&lt;/code&gt;? O que me destravou foi perceber que Compose não era só um jeito novo de fazer a mesma coisa, mas uma forma declarativa de construir UI. E, vindo do React, foi aí que tudo começou a fazer sentido.&lt;/p&gt;

&lt;h2&gt;
  
  
  A primeira virada de chave
&lt;/h2&gt;

&lt;p&gt;A principal virada de chave para mim foi perceber que o Compose não era “Android sem XML”. No React, a gente já está acostumado com a ideia de que a interface responde ao estado. No Compose, a lógica é parecida: você descreve a UI com funções @Composable, usa estado, e o framework atualiza o que precisa quando esse estado muda. Não é o mesmo modelo do React, mas a ideia de “descrever a interface em vez de montar tudo manualmente” está ali. Quando eu passei a enxergar o Compose assim, ele começou a fazer muito mais sentido.&lt;/p&gt;

&lt;h2&gt;
  
  
  Row, Column e Box me fizeram parar de brigar com layout
&lt;/h2&gt;

&lt;p&gt;A parte de layout foi uma das primeiras coisas que me deixou confortável. Row e Column são quase autoexplicativos. Um organiza na horizontal, o outro na vertical. E o Box resolve aqueles casos em que você quer empilhar coisas ou alinhar um elemento dentro de uma área. Não é CSS. Mas, se você já trabalhou com flexbox, a sensação não é tão distante.&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="c1"&gt;// código React&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ProfileHeader&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
      &lt;span class="na"&gt;style&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="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;flexDirection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;row&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&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="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;img&lt;/span&gt;
        &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/avatar.png"&lt;/span&gt;
        &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Avatar"&lt;/span&gt;
        &lt;span class="na"&gt;style&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="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;999&lt;/span&gt;&lt;span class="p"&gt;,&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="nt"&gt;div&lt;/span&gt;
        &lt;span class="na"&gt;style&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="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;flexDirection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;column&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="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;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Marcos&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;strong&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;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Android + Backend&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&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;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// código Compose&lt;/span&gt;
&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;ProfileHeader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillMaxWidth&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;verticalAlignment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Alignment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CenterVertically&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;horizontalArrangement&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Arrangement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spacedBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&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="nc"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;painter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;painterResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drawable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;contentDescription&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Avatar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CircleShape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nc"&gt;Column&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Marcos"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MaterialTheme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;typography&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;titleMedium&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Android + Backend"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MaterialTheme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;typography&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bodyMedium&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;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O que eu gostei aqui é que o layout fica muito explícito. Você bate o olho e entende a estrutura da tela sem precisar ficar pulando entre XML, style, tema e código.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modifier foi a peça que mais me confundiu no começo
&lt;/h2&gt;

&lt;p&gt;Se teve uma coisa que me pegou de verdade foi Modifier. No início eu pensava nele quase como um “style” do Compose. Só que não é só isso. Com Modifier, você mexe em tamanho, espaçamento, comportamento, clique, borda, background, clipping, alinhamento… e o detalhe mais importante: a ordem importa.&lt;/p&gt;

&lt;p&gt;Isso parece pequeno até você perceber que:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;padding&lt;/strong&gt; antes ou depois de &lt;strong&gt;clickable&lt;/strong&gt; muda a área clicável&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;clip&lt;/strong&gt; antes ou depois de &lt;strong&gt;background&lt;/strong&gt; muda o resultado visual&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;border&lt;/strong&gt;, &lt;strong&gt;padding&lt;/strong&gt; e &lt;strong&gt;background&lt;/strong&gt; não são intercambiáveis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Foi uma das partes em que eu mais apanhei, porque no começo eu só encadeava as coisas até “ficar com cara certa”. Depois entendi que ali existe uma lógica mesmo.&lt;/p&gt;

&lt;p&gt;Um exemplo simples&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;SelectableCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;onClick&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;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nd"&gt;@Composable&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;borderColor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xFF4F46E5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nc"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xFFE5E7EB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RoundedCornerShape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;border&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;borderColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RoundedCornerShape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clickable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&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="nf"&gt;content&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;Depois que eu entendi que Modifier não era enfeite, mas parte da lógica visual e interativa da UI, muita coisa ficou mais previsível.&lt;/p&gt;

&lt;h2&gt;
  
  
  O lado bom: if, when e loops são só Kotlin
&lt;/h2&gt;

&lt;p&gt;Uma coisa que eu gostei rápido no Compose foi não precisar entrar naquele modo mental de “template + expressão” toda hora. No React, embora tudo esteja dentro do JavaScript, ainda existe aquela mistura constante entre JSX e lógica de renderização. No Compose, a interface já é código Kotlin desde o começo. Então você usa if, when, for e outras estruturas da linguagem de forma direta, sem sentir que está alternando entre marcação e lógica o tempo todo. &lt;/p&gt;

&lt;h2&gt;
  
  
  Input controlado continua sendo input controlado
&lt;/h2&gt;

&lt;p&gt;Essa parte foi das mais tranquilas pra mim porque lembra muito o React. Se você já trabalhou com input controlado, não tem muito mistério. O valor vem do estado, o onValueChange atualiza esse estado, e a UI reage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;NameForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&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="nc"&gt;OutlinedTextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;onValueChange&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Nome"&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isNotBlank&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, $name"&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;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pra mim, o que muda de verdade aqui não é o conceito de estado, e sim o vocabulário que o Compose usa para lidar com isso. Se no React a gente pensa em useState e no ciclo de renderização do componente, no Compose essa conversa passa muito por remember, mutableStateOf e rememberSaveable. O remember eu comecei a enxergar como aquele estado que continua existindo entre recomposições. Já o rememberSaveable fica mais próximo daqueles casos em que você quer preservar melhor a informação da tela, por exemplo em uma rotação, sem simplesmente perder tudo que o usuário já fez.&lt;/p&gt;

&lt;h2&gt;
  
  
  LazyColumn foi onde o Compose começou a ficar familiar
&lt;/h2&gt;

&lt;p&gt;Quando cheguei em lista, tudo começou a parecer menos “mundo novo”. No Compose, &lt;strong&gt;LazyColumn&lt;/strong&gt; é aquele componente que você naturalmente usa pra listas maiores, renderizando só o necessário. E aí entra uma coisa que pra quem vem do React já deveria soar conhecida a identidade do item importa. Se existe um &lt;strong&gt;id&lt;/strong&gt;, usa esse &lt;strong&gt;id&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;Hero&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;HeroList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;heroes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Hero&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
    &lt;span class="n"&gt;selectedId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?,&lt;/span&gt;
    &lt;span class="n"&gt;onSelect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;LazyColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;contentPadding&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PaddingValues&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;verticalArrangement&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Arrangement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spacedBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&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="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;heroes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&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="n"&gt;hero&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="nc"&gt;SelectableCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;selected&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hero&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;selectedId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;onSelect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hero&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&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;{&lt;/span&gt;
                &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hero&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&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;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  O padrão stateful/stateless me ajudou bastante
&lt;/h2&gt;

&lt;p&gt;Outra coisa que eu trouxe do React foi separar melhor o que segura estado do que só renderiza, me ajudou muito pensar assim:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a tela principal segura o estado&lt;/li&gt;
&lt;li&gt;os componentes menores recebem dados e callbacks
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;ChooseHeroScreen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;heroes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Hero&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;selectedId&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;rememberSaveable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;topBar&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;TopAppBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Qual é seu herói favorito?"&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;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;innerPadding&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="nc"&gt;HeroList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;heroes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;heroes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;selectedId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;selectedId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;onSelect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;selectedId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;innerPadding&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;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso conversa muito com state hoisting, que é outro conceito que no começo parece nome bonito pra algo simples deixar o estado subir para um nível mais apropriado.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que mais me atrapalhou vindo do React
&lt;/h2&gt;

&lt;p&gt;Algumas coisas me fizeram perder mais tempo do que eu gostaria:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Achar que &lt;strong&gt;Modifier&lt;/strong&gt; era só estilo&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Não é. Ele mexe com layout, interação e até semântica.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Ignorar a ordem das coisas&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No Compose, a ordem muda bastante o resultado.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Colocar estado cedo demais no componente errado&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quando eu deixava componente pequeno segurando regra demais, rapidamente ficava chato de reaproveitar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Subestimar &lt;strong&gt;rememberSaveable&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tem tela em que perder estado por besteira é irritante.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Tratar Compose como XML com sintaxe diferente&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Esse foi provavelmente o maior erro de todos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No fim das contas&lt;/p&gt;

&lt;p&gt;Hoje, se eu tivesse que explicar Jetpack Compose de um jeito simples, eu diria que ele me pareceu uma mistura de três coisas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a mentalidade declarativa que eu já conhecia de React&lt;/li&gt;
&lt;li&gt;a estrutura forte de uma UI nativa Android&lt;/li&gt;
&lt;li&gt;a praticidade de escrever tudo em Kotlin, sem ficar alternando demais de contexto&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O que mais me ajudou a sair da trava inicial foi parar de tentar decorar API e focar em entender alguns blocos básicos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Row, Column e Box&lt;/li&gt;
&lt;li&gt;Modifier&lt;/li&gt;
&lt;li&gt;remember e rememberSaveable&lt;/li&gt;
&lt;li&gt;LazyColumn&lt;/li&gt;
&lt;li&gt;state hoisting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Depois disso, o resto começou a parecer menos intimidador.&lt;/p&gt;

&lt;p&gt;Compose ainda tem muita coisa que eu estou aprendendo. Mas, honestamente, depois que esse modelo mental encaixa, a experiência fica bem melhor do que eu imaginava quando comecei.&lt;/p&gt;

</description>
      <category>jetpackcompose</category>
      <category>kotlin</category>
      <category>android</category>
      <category>development</category>
    </item>
    <item>
      <title>Client-Side Rendering (CSR)</title>
      <dc:creator>Marcos Anjos</dc:creator>
      <pubDate>Thu, 24 Oct 2024 00:53:53 +0000</pubDate>
      <link>https://dev.to/nullref/client-side-rendering-csr-98j</link>
      <guid>https://dev.to/nullref/client-side-rendering-csr-98j</guid>
      <description>&lt;p&gt;&lt;em&gt;Client-Side Rendering&lt;/em&gt; (CSR) é uma técnica comum no desenvolvimento Web moderno, usada para criar aplicações interativas e dinâmicas. Com essa técnica retiramos do servidor a responsabilidade de renderizar a página e trazemos para o lado do cliente, deixando o servidor cuidar do que é mais importante para ele, as regras de negócio. Fazendo essa separação se fez possível oferecer uma experiência de usuário mais fluida, dinâmica e possibilita a criação de novos tipos de aplicações. As vantagens são diversas, mas  ao mesmo tempo há &lt;em&gt;trade-offs&lt;/em&gt; que devem ser avaliados em cada projeto se vale ou não a pena adotar essa técnica. &lt;/p&gt;

&lt;h3&gt;
  
  
  O que é &lt;em&gt;Client-Side Rendering&lt;/em&gt; (CSR)?
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Client-side rendering&lt;/em&gt; ou apenas CSR, é uma técnica de desenvolvimento de aplicações dinâmicas onde a renderização da interface ocorre no lado do cliente (navegador). Diferente de como era feito antes dessa técnica se tornar popular, onde o servidor era responsável por fazer esse papel de renderizar a página, retornando ao cliente um arquivo HTML com todo o conteúdo já montado. &lt;/p&gt;

&lt;p&gt;Com o CSR passamos o papel de renderizar a página para o navegador (cliente). O servidor apenas envia um arquivo HTML básico que internamente contém links para arquivos Javascript. Ao receber esse HTML o navegador faz download dos arquivos Javascript referenciados que são os responsáveis por renderizar o conteúdo da página. A vantagem do CRS é que uma vez carregado os arquivos Javascript o conteúdo pode ser atualizado dinamicamente sem depender de novas requisições ao servidor. Deixando a experiência de navegação mais fluida para usuário. O CSR é geralmente utilizado em aplicações onde há a necessidade de interações em tempo real ou conteúdos muito dinâmicos como, por exemplo, em &lt;em&gt;single-page applications&lt;/em&gt; (SPA). Sendo uma solução para páginas internas,  dashboards, ou sistemas onde não há a necessidade de SEO.&lt;/p&gt;

&lt;h3&gt;
  
  
  Como &lt;em&gt;Client-Side Rendering&lt;/em&gt; funciona?
&lt;/h3&gt;

&lt;p&gt;Um exemplo de fluxo de renderização utilizando &lt;em&gt;Client-Side Rendering&lt;/em&gt;, seria:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;O usuário acessa uma página web, que internamente envia uma requisição ao servidor.&lt;br&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%2F03qgafwib89icr6avyem.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%2F03qgafwib89icr6avyem.png" alt="Barra de pesquisa" width="800" height="54"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;O servidor recebe a requisição e responde enviando um HTML básico contendo praticamente  apenas links para arquivos JavaScript e CSS. &lt;br&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%2Fzbieo31qu6lav1jsqh6x.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%2Fzbieo31qu6lav1jsqh6x.png" alt="Código HTML" width="800" height="487"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;O navegador faz o download desse HTML e, assim que terminado, envia novas requisições para baixar os arquivos JavaScript e CSS que estavam referenciados no HTML. &lt;br&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%2Fxgtg5170ivg973a0jmcd.gif" 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%2Fxgtg5170ivg973a0jmcd.gif" alt="Console navegador requisições" width="844" height="496"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Com os arquivos JavaScript tendo sido baixados eles serão executados e o processo de renderizar a página será realizado. &lt;br&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%2Fl36h5yr652f998c6t1x9.gif" 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%2Fl36h5yr652f998c6t1x9.gif" alt="Navegador carregando página" width="640" height="348"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A partir desse ponto, o JavaScript controla toda aplicação e as interações do usuário, atualizando o conteúdo da página de forma dinâmica, sem novas requisições ao servidor.  &lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2F6twtab19d2nke5z0i3g3.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%2F6twtab19d2nke5z0i3g3.png" alt="Fluxo Client-Side Rendering" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Vantagens do &lt;em&gt;Client-Side Rendering&lt;/em&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Velocidade: A navegação entre as páginas dentro de uma CSR é extremamente rápida, pois não há a necessidade de fazer várias requisições ao servidor após o carregamento inicial.&lt;/li&gt;
&lt;li&gt;Experiência do Usuários: uso CSR são altamente inteiráveis e apresentam ótimo desempenho, proporcionando uma experiência semelhante a aplicativos nativos.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Separation of Concerns&lt;/em&gt;: O CSR possibilita a separação entre o Front-end e Back-end, permitindo que o Front-end seja completamente gerido pelo JS, enquanto Back-end cuida apenas dos dados e da lógica do negócio.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Desvantagens do &lt;em&gt;Client-Side Rendering&lt;/em&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Alta carga de JS: Em aplicações grandes, os arquivos JS podem se tornar muito pesados, o que pode prejudicar a experiência do usuário, especialmente no carregamento inicial da aplicação.&lt;/li&gt;
&lt;li&gt;Problemas de SEO: Como o conteúdo da página renderizado no lado do cliente, os motores de busca têm dificuldades em indexar o conteúdo, já que eles precisam do HTML renderizado e numa aplicação com CSR o HTML está praticamente vazio. Isso pode ser uma desvantagens para aplicações que dependem de SEO como &lt;em&gt;landing pages&lt;/em&gt; e &lt;em&gt;e-commerces&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Dependente do cliente: Como a aplicação é executada no lado do cliente, há uma dependência de quanto recurso o mesmo possui, podendo afetar negativamente a experiência do usuário caso seu dispositivo tenha poucos recursos. Além disso, se o dispositivo estiver com a execução de JavaScript desabilitada a aplicação não ira funcionar.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Neste artigo, apresentamos principais pontos importantes sobre o uso do CSR, apresentando os fundamentos e suas vantagens e desvantagens. Através do fluxo CSR, conhecemos as etapas principais como que funciona o ciclo de vida do CSR. Podemos perceber a importância do JavaScript para proporcionar as aplicações que rodam inteiramente no lado do cliente.  Apesar dos benefícios do CSR relacionados a experiência do usuário, fica evidente que esse técnica de renderização possui algumas desvantagens relacionado alta carga de JavaScript e problemas relacionados a SEO. &lt;/p&gt;

&lt;p&gt;Para contornar as limitações do CSR,  temos soluções como o &lt;em&gt;Static Site Generation&lt;/em&gt; (SSG) e &lt;em&gt;Server-Side Rendering&lt;/em&gt; (SSR). No SSG, as páginas são geradas de forma estática durante o período de &lt;em&gt;build&lt;/em&gt;, resultando em HTML já pronto para ser entregue ao cliente. E no caso do SSR, a renderização é feita no lado do servidor que responde com um HTML já renderizado para o cliente.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>nextjs</category>
    </item>
  </channel>
</rss>
