<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://docs.mockmerce.com.br/diario</id>
    <title>Diário de Aula · 2TDSPG</title>
    <updated>2026-08-03T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://docs.mockmerce.com.br/diario"/>
    <subtitle>O passo a passo de cada aula da turma.</subtitle>
    <icon>https://docs.mockmerce.com.br/img/favicon.svg</icon>
    <entry>
        <title type="html"><![CDATA[Semana 1 — A camada de serviços (Axios): um lugar só para falar com a API]]></title>
        <id>https://docs.mockmerce.com.br/diario/semana-01-camada-de-servicos</id>
        <link href="https://docs.mockmerce.com.br/diario/semana-01-camada-de-servicos"/>
        <updated>2026-08-03T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Na primeira semana montamos a base de tudo que vem depois: uma camada de serviços em]]></summary>
        <content type="html"><![CDATA[<p>Na primeira semana montamos a base de tudo que vem depois: uma <strong>camada de serviços</strong> em
Axios que centraliza <strong>como</strong> o app conversa com a API da turma — instância única,
headers automáticos, injeção de token e <strong>tratamento de erro num lugar só</strong>.</p>
<blockquote>
<p><strong>A ideia da semana:</strong> nenhuma tela chama <code>axios</code> direto. A tela pede a um <strong>serviço</strong>;
o serviço sabe falar com a API. Assim, quando algo muda (URL, header, erro), muda <strong>num
arquivo só</strong>.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="por-que-não-chamar-a-api-direto-na-tela">Por que não chamar a API direto na tela<a href="https://docs.mockmerce.com.br/diario/semana-01-camada-de-servicos#por-que-n%C3%A3o-chamar-a-api-direto-na-tela" class="hash-link" aria-label="Link direto para Por que não chamar a API direto na tela" title="Link direto para Por que não chamar a API direto na tela" translate="no">​</a></h2>
<p>Se cada tela montar sua própria requisição, a gente repete headers, repete <code>try/catch</code>,
repete o jeito de ler o erro — e no dia que a API muda, caça-se <code>fetch</code> por todo o app. A
camada de serviços resolve isso: <strong>um</strong> cliente HTTP configurado, e funções tipadas por
cima dele.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="o-que-construímos">O que construímos<a href="https://docs.mockmerce.com.br/diario/semana-01-camada-de-servicos#o-que-constru%C3%ADmos" class="hash-link" aria-label="Link direto para O que construímos" title="Link direto para O que construímos" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-a-instância-http--srcserviceshttpts">1. A instância HTTP — <code>src/services/http.ts</code><a href="https://docs.mockmerce.com.br/diario/semana-01-camada-de-servicos#1-a-inst%C3%A2ncia-http--srcserviceshttpts" class="hash-link" aria-label="Link direto para 1-a-instância-http--srcserviceshttpts" title="Link direto para 1-a-instância-http--srcserviceshttpts" translate="no">​</a></h3>
<p>Um cliente Axios com <code>baseURL</code>, <code>timeout</code> e os <strong>headers que vão em toda requisição</strong>:
<code>X-API-Key</code> (identifica o grupo) e <code>X-Student-RM</code> (rastreia quem está codando — isso conta
na avaliação).</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> http </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> axios</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  baseURL</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation">env</span><span class="token template-string interpolation punctuation" style="color:#393A34">.</span><span class="token template-string interpolation property-access">apiUrl</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string string" style="color:#e3116c">/v1</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  timeout</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15000</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  headers</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string-property property" style="color:#36acaa">'Content-Type'</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'application/json'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string-property property" style="color:#36acaa">'X-API-Key'</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> env</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">apiKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string-property property" style="color:#36acaa">'X-Student-RM'</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> env</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">studentRm</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-interceptor-de-request--o-token-entra-sozinho">2. Interceptor de request — o token entra sozinho<a href="https://docs.mockmerce.com.br/diario/semana-01-camada-de-servicos#2-interceptor-de-request--o-token-entra-sozinho" class="hash-link" aria-label="Link direto para 2. Interceptor de request — o token entra sozinho" title="Link direto para 2. Interceptor de request — o token entra sozinho" translate="no">​</a></h3>
<p>O comprador loga e recebe um token. Em vez de lembrar de anexá-lo em cada chamada, um
<strong>interceptor</strong> injeta o <code>Authorization: Bearer</code> quando existe token, e o remove quando não:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> customerToken</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token keyword null nil" style="color:#00009f">null</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword null nil" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setCustomerToken</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">token</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token keyword null nil" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> customerToken </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> token</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">http</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">interceptors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">config</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">customerToken</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> config</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">headers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">set</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'Authorization'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token template-string string" style="color:#e3116c">Bearer </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation">customerToken</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">else</span><span class="token plain"> config</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">headers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">delete</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'Authorization'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> config</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-interceptor-de-response--um-tratamento-de-erro-para-o-app-inteiro">3. Interceptor de response — <strong>um</strong> tratamento de erro para o app inteiro<a href="https://docs.mockmerce.com.br/diario/semana-01-camada-de-servicos#3-interceptor-de-response--um-tratamento-de-erro-para-o-app-inteiro" class="hash-link" aria-label="Link direto para 3-interceptor-de-response--um-tratamento-de-erro-para-o-app-inteiro" title="Link direto para 3-interceptor-de-response--um-tratamento-de-erro-para-o-app-inteiro" translate="no">​</a></h3>
<p>Aqui está o pulo do gato da semana: toda falha vira um <strong><code>ApiError</code></strong> com <code>code</code>,
<code>message</code> e <code>status</code>. A tela nunca precisa cavar <code>error.response.data.error</code> — ela recebe
um erro previsível e tipado.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">http</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">interceptors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">response</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">use</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">response</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> response</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> status </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> error</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">response</span><span class="token operator" style="color:#393A34">?.</span><span class="token plain">status </span><span class="token operator" style="color:#393A34">??</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> payload </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> error</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">response</span><span class="token operator" style="color:#393A34">?.</span><span class="token plain">data</span><span class="token operator" style="color:#393A34">?.</span><span class="token plain">error</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword control-flow" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">payload</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token known-class-name class-name">Promise</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">reject</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name known-class-name class-name">ApiError</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">payload</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">code</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">??</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'ERROR'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> payload</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">message</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">??</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'Erro na API'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> status</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword control-flow" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">error</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">code</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">===</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'ECONNABORTED'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token known-class-name class-name">Promise</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">reject</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name known-class-name class-name">ApiError</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'TIMEOUT'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'A requisição demorou demais.'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> status</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token known-class-name class-name">Promise</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">reject</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name known-class-name class-name">ApiError</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'NETWORK_ERROR'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'Sem conexão com o servidor. Confira a URL da API.'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> status</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>O caminho de uma requisição, de ponta a ponta:</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-serviços-tipados-por-recurso">4. Serviços tipados por recurso<a href="https://docs.mockmerce.com.br/diario/semana-01-camada-de-servicos#4-servi%C3%A7os-tipados-por-recurso" class="hash-link" aria-label="Link direto para 4. Serviços tipados por recurso" title="Link direto para 4. Serviços tipados por recurso" translate="no">​</a></h3>
<p>Por cima da instância, funções pequenas e <strong>tipadas</strong> — a tela pede o dado, não sabe de HTTP:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// src/services/products.ts</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">listProducts</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">params</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token maybe-class-name">ListProductsParams</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Promise</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token maybe-class-name">Paginated</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token maybe-class-name">ProductSummary</span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> data </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> http</span><span class="token punctuation" style="color:#393A34">.</span><span class="token generic-function function" style="color:#d73a49">get</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name maybe-class-name">Paginated</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name maybe-class-name">ProductSummary</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'/products'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> params </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getProduct</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Promise</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token maybe-class-name">Product</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> data </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> http</span><span class="token punctuation" style="color:#393A34">.</span><span class="token generic-function function" style="color:#d73a49">get</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name maybe-class-name">Product</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token template-string string" style="color:#e3116c">/products/</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation">id</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>Também deixamos prontos <code>cart.ts</code> (<code>getCart</code>, <code>addCartItem</code>, <code>updateCartItem</code>,
<code>removeCartItem</code>) e <code>auth.ts</code> (<code>login</code>, <code>register</code>) — todos no mesmo padrão.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-os-tipos-da-api--srctypesapits">5. Os tipos da API — <code>src/types/api.ts</code><a href="https://docs.mockmerce.com.br/diario/semana-01-camada-de-servicos#5-os-tipos-da-api--srctypesapits" class="hash-link" aria-label="Link direto para 5-os-tipos-da-api--srctypesapits" title="Link direto para 5-os-tipos-da-api--srctypesapits" translate="no">​</a></h3>
<p><code>Paginated&lt;T&gt;</code>, <code>ProductSummary</code>, <code>Product</code> (com <code>variants[]</code>), <code>Cart</code>, e a classe
<code>ApiError</code>. Tipar aqui é o que faz o autocomplete funcionar no app inteiro e mata o <code>any</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="as-telas-consumindo-na-mão">As telas (consumindo "na mão")<a href="https://docs.mockmerce.com.br/diario/semana-01-camada-de-servicos#as-telas-consumindo-na-m%C3%A3o" class="hash-link" aria-label="Link direto para As telas (consumindo &quot;na mão&quot;)" title="Link direto para As telas (consumindo &quot;na mão&quot;)" translate="no">​</a></h2>
<p>Com os serviços prontos, as telas de <strong>lista</strong> e <strong>detalhe</strong> buscam com <code>useState</code> +
<code>useEffect</code>, tratando loading/erro na unha. O carrinho ficou como <strong>placeholder</strong>.</p>
<p>Funciona — mas repare em quanta coisa a tela gerencia:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">produtos</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> setProdutos</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token generic-function function" style="color:#d73a49">useState</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name maybe-class-name">ProductSummary</span><span class="token generic-function generic class-name punctuation" style="color:#393A34">[</span><span class="token generic-function generic class-name punctuation" style="color:#393A34">]</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">loading</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> setLoading</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useState</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">erro</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> setErro</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token generic-function function" style="color:#d73a49">useState</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name builtin">string</span><span class="token generic-function generic class-name"> </span><span class="token generic-function generic class-name operator" style="color:#393A34">|</span><span class="token generic-function generic class-name"> </span><span class="token generic-function generic class-name keyword null nil" style="color:#00009f">null</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword null nil" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">useEffect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> vivo </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">listProducts</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">then</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">res</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> vivo </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setProdutos</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">res</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword control-flow" style="color:#00009f">catch</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> vivo </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setErro</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">message</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword control-flow" style="color:#00009f">finally</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> vivo </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setLoading</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> vivo </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<blockquote>
<p><strong>Gancho para a Semana 2:</strong> guardem essa sensação de "gerenciar dado na mão". É
exatamente isso que o <strong>TanStack Query</strong> vem aposentar — cache, revalidação e estados
prontos. A camada de serviços continua; o Query só orquestra o que ela já faz.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="regras-de-ouro-valem-o-semestre-todo">Regras de ouro (valem o semestre todo)<a href="https://docs.mockmerce.com.br/diario/semana-01-camada-de-servicos#regras-de-ouro-valem-o-semestre-todo" class="hash-link" aria-label="Link direto para Regras de ouro (valem o semestre todo)" title="Link direto para Regras de ouro (valem o semestre todo)" translate="no">​</a></h2>
<ul>
<li class=""><strong>A unidade vendável é a VARIANTE.</strong> Carrinho usa <code>variantId</code>; preço/estoque vêm em
<code>product.variants[]</code> (no detalhe), não na listagem.</li>
<li class=""><strong>Headers sempre:</strong> <code>X-API-Key</code> e <code>X-Student-RM</code>. Rotas de comprador exigem também o
<code>Authorization: Bearer</code> (que o interceptor injeta).</li>
<li class=""><strong>Sem <code>any</code></strong> sem justificativa documentada — é penalidade nos checkpoints.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="lembretes-de-api">Lembretes de API<a href="https://docs.mockmerce.com.br/diario/semana-01-camada-de-servicos#lembretes-de-api" class="hash-link" aria-label="Link direto para Lembretes de API" title="Link direto para Lembretes de API" translate="no">​</a></h2>
<ul>
<li class=""><strong>Base (nuvem):</strong> <code>https://api.mockmerce.com.br/v1</code>. Os apps conectam no backend <strong>na
nuvem</strong>, não em <code>localhost</code> — no app, isso vem de <code>env.apiUrl</code>.</li>
<li class="">Documentação viva (Swagger): <code>https://api.mockmerce.com.br/docs</code>.</li>
</ul>]]></content>
        <author>
            <name>Professor · 2TDSPG</name>
        </author>
        <category label="React Native" term="React Native"/>
        <category label="Axios" term="Axios"/>
        <category label="Semana 1" term="Semana 1"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Semana 2 · Segunda — TanStack Query: pare de cuidar dos dados na mão]]></title>
        <id>https://docs.mockmerce.com.br/diario/semana-02-tanstack-query</id>
        <link href="https://docs.mockmerce.com.br/diario/semana-02-tanstack-query"/>
        <updated>2026-08-10T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Hoje começamos a Semana 2 — Consumo e Integração com API · pt. 2. Construímos direto]]></summary>
        <content type="html"><![CDATA[<p>Hoje começamos a <strong>Semana 2 — Consumo e Integração com API · pt. 2</strong>. Construímos direto
sobre a camada de serviços (Axios) da Semana 1 e adicionamos o <strong>TanStack Query</strong>: cache,
revalidação e mutations otimistas.</p>
<blockquote>
<p><strong>A frase da semana:</strong> na Semana 1 a gente aprendeu a <strong>buscar</strong> dados. Nesta semana a
gente para de <strong>cuidar</strong> deles na mão.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="por-que-trocar-useeffect--usestate">Por que trocar <code>useEffect</code> + <code>useState</code><a href="https://docs.mockmerce.com.br/diario/semana-02-tanstack-query#por-que-trocar-useeffect--usestate" class="hash-link" aria-label="Link direto para por-que-trocar-useeffect--usestate" title="Link direto para por-que-trocar-useeffect--usestate" translate="no">​</a></h2>
<p>Partimos da tela da Semana 1 que busca produtos manualmente:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// Funciona — mas repare em quanta coisa a gente gerencia:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">produtos</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> setProdutos</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token generic-function function" style="color:#d73a49">useState</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name maybe-class-name">ProductSummary</span><span class="token generic-function generic class-name punctuation" style="color:#393A34">[</span><span class="token generic-function generic class-name punctuation" style="color:#393A34">]</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">loading</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> setLoading</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useState</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">erro</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> setErro</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token generic-function function" style="color:#d73a49">useState</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name builtin">string</span><span class="token generic-function generic class-name"> </span><span class="token generic-function generic class-name operator" style="color:#393A34">|</span><span class="token generic-function generic class-name"> </span><span class="token generic-function generic class-name keyword null nil" style="color:#00009f">null</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword null nil" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">useEffect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> vivo </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">setLoading</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">listProducts</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">then</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">res</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> vivo </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setProdutos</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">res</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword control-flow" style="color:#00009f">catch</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> vivo </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setErro</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">message</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword control-flow" style="color:#00009f">finally</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> vivo </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setLoading</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> vivo </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Três dores que ficaram no ar (guarde-as — o Query mata as três):</p>
<ol>
<li class="">A <strong>mesma</strong> busca em 3 telas = <strong>3 requests</strong>, mesmo com dado idêntico.</li>
<li class="">Voltar para uma tela já visitada mostra <strong>spinner de novo</strong>.</li>
<li class="">Aquele <code>let vivo = true</code> existe só para não dar <code>setState</code> em componente desmontado.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="o-modelo-mental-só-três-ideias">O modelo mental (só três ideias)<a href="https://docs.mockmerce.com.br/diario/semana-02-tanstack-query#o-modelo-mental-s%C3%B3-tr%C3%AAs-ideias" class="hash-link" aria-label="Link direto para O modelo mental (só três ideias)" title="Link direto para O modelo mental (só três ideias)" translate="no">​</a></h2>
<!-- -->
<ul>
<li class=""><strong>Query = leitura</strong>, identificada por uma <strong>key</strong>. A key é o "endereço" do dado no cache.</li>
<li class=""><strong>staleTime</strong> = por quanto tempo o dado é "fresco". Fresco <strong>não</strong> refaz request.</li>
<li class=""><strong>Mutation = escrita</strong> (POST/PATCH/DELETE). Depois de escrever, a gente <strong>invalida</strong> a
leitura para ela se atualizar.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="o-que-escrevemos-ao-vivo">O que escrevemos ao vivo<a href="https://docs.mockmerce.com.br/diario/semana-02-tanstack-query#o-que-escrevemos-ao-vivo" class="hash-link" aria-label="Link direto para O que escrevemos ao vivo" title="Link direto para O que escrevemos ao vivo" translate="no">​</a></h2>
<p><strong>1. O <code>QueryClient</code></strong> — <code>src/lib/queryClient.ts</code>, com <code>staleTime</code> e um <code>retry</code> que <strong>não</strong>
repete em 4xx (401/404/422 não melhoram com retry).</p>
<p><strong>2. O provider</strong> — envolvemos o app com <code>&lt;QueryClientProvider&gt;</code> no <code>App.tsx</code>. <strong>A ordem
importa:</strong> o Query fica <strong>por fora</strong> do <code>SessionProvider</code>, porque a sessão usa <code>useQueryClient</code>.</p>
<p><strong>3. A primeira query</strong> — trocamos a tela da retomada por um hook:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// src/hooks/useProducts.ts</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useProducts</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">params </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useQuery</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    queryKey</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">'products'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'list'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> params</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// os params ENTRAM na key</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function-variable function" style="color:#d73a49">queryFn</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">listProducts</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">params</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// na tela:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> isLoading</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> isError</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> error</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> refetch </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useProducts</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Rodamos e fizemos o teste: entrar no produto, voltar para a lista → <strong>não pisca spinner</strong>
(veio do cache). Foi o momento "uau" do dia.</p>
<p><strong>4. Query keys</strong> — a lição que evita 80% dos bugs do semestre:</p>
<blockquote>
<p>Quem <strong>lê</strong> e quem <strong>invalida</strong> têm que usar a <strong>mesma</strong> key. Se um usa <code>['products']</code> e o
outro <code>['product']</code>, a invalidação não acontece — e você jura que "o Query está bugado".
Não está: a key não bateu.</p>
</blockquote>
<p>A key inclui os <code>params</code> de busca — procurar "camisa" e "tênis" são <strong>dois caches</strong> distintos.</p>
<p><strong>5. Mutation + atualização otimista</strong> — o ápice. O ciclo de uma escrita otimista:</p>
<!-- -->
<p>Mostramos os dois caminhos:</p>
<ul>
<li class=""><strong>Feliz:</strong> clicar em "adicionar" → o item aparece no carrinho <strong>na hora</strong>, antes da resposta.</li>
<li class=""><strong>Triste:</strong> com o backend fora, o item aparece e <strong>some</strong> (rollback). Isso é honestidade de
UI: mostramos o otimismo, mas não mentimos quando falha.</li>
</ul>
<blockquote>
<p><strong>Detalhe que separa nota 7 de nota 10:</strong> para pintar o item otimista precisamos de <code>name</code> e
<code>unitPrice</code> <strong>na mão</strong> — o servidor tem, mas ainda não recebemos a resposta. Por isso a
mutation recebe esses campos. Otimismo custa um pouquinho de dado local.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="mão-na-massa-em-aula">Mão na massa (em aula)<a href="https://docs.mockmerce.com.br/diario/semana-02-tanstack-query#m%C3%A3o-na-massa-em-aula" class="hash-link" aria-label="Link direto para Mão na massa (em aula)" title="Link direto para Mão na massa (em aula)" translate="no">​</a></h2>
<p>Cada grupo, no próprio app, <strong>migrou a tela de listagem para <code>useProducts</code></strong>: lista via
<code>useQuery</code>, com <code>isLoading</code> e <code>isError</code> tratados. O erro nº 1 foi <strong>esquecer o
<code>QueryClientProvider</code></strong> — se a sua lista não carregou, comece por aí.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="-dever-de-casa-segunda--quarta--40-min">📌 Dever de casa (segunda → quarta) · ~40 min<a href="https://docs.mockmerce.com.br/diario/semana-02-tanstack-query#-dever-de-casa-segunda--quarta--40-min" class="hash-link" aria-label="Link direto para 📌 Dever de casa (segunda → quarta) · ~40 min" title="Link direto para 📌 Dever de casa (segunda → quarta) · ~40 min" translate="no">​</a></h2>
<p>Entregar no <strong>início da aula de quarta (12/08)</strong>. Feito no app do seu grupo, consumindo a API
da turma. Use o <code>X-Student-RM</code> de <strong>quem está codando</strong> — isso conta na avaliação.</p>
<ol>
<li class=""><strong>Instale e ligue o Query.</strong> <code>npm i @tanstack/react-query</code>. Envolva o app com
<code>&lt;QueryClientProvider&gt;</code> usando um <code>QueryClient</code> criado em arquivo próprio.</li>
<li class=""><strong>Migre a listagem</strong> para <code>useProducts()</code> com <code>useQuery</code>. A tela trata <code>isLoading</code>
(spinner), <code>isError</code> (mensagem + botão de tentar de novo) e a <strong>lista vazia</strong>.</li>
<li class=""><strong>Busca:</strong> ligue um <code>TextInput</code> de busca que faça <strong>parte da query key</strong>
(<code>['products','list',{ search }]</code>). Buscas diferentes viram caches diferentes; voltar a
uma busca já feita é instantâneo.</li>
<li class=""><strong>Responda em 2 linhas no README do grupo:</strong> ao digitar rápido no campo de busca, quantas
requests saem e por quê? (Dica: <code>staleTime</code> e <code>placeholderData</code>.)</li>
</ol>
<p><strong>Critério de pronto:</strong> lista carrega via <code>useQuery</code>; <strong>sem</strong> <code>useEffect</code>/<code>useState</code> para
data/loading/erro na tela; a busca reflete na query key.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="quarta--carrinho-e-mutations-o-código-completo">Quarta — carrinho e mutations (o código completo)<a href="https://docs.mockmerce.com.br/diario/semana-02-tanstack-query#quarta--carrinho-e-mutations-o-c%C3%B3digo-completo" class="hash-link" aria-label="Link direto para Quarta — carrinho e mutations (o código completo)" title="Link direto para Quarta — carrinho e mutations (o código completo)" translate="no">​</a></h2>
<p>Venham com a lista <strong>já migrada</strong>. A quarta é o código do carrinho, em três blocos.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="bloco-1--useproductid--adicionar-ao-carrinho">Bloco 1 — <code>useProduct(id)</code> + adicionar ao carrinho<a href="https://docs.mockmerce.com.br/diario/semana-02-tanstack-query#bloco-1--useproductid--adicionar-ao-carrinho" class="hash-link" aria-label="Link direto para bloco-1--useproductid--adicionar-ao-carrinho" title="Link direto para bloco-1--useproductid--adicionar-ao-carrinho" translate="no">​</a></h3>
<p>O detalhe é uma query de <strong>um</strong> item. Lembre: preço e estoque vivem em <code>variants[]</code>.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">src/hooks/useProduct.ts</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> useQuery </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@tanstack/react-query'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> getProduct </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@/services/products'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> queryKeys </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@/lib/queryKeys'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useProduct</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useQuery</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    queryKey</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> queryKeys</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">products</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">detail</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function-variable function" style="color:#d73a49">queryFn</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getProduct</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    enabled</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Boolean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// não dispara com id vazio</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>Na tela de detalhe, escolhemos a variante e disparamos a mutation de adicionar:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">src/screens/ProductDetailScreen.tsx (essencial)</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> data</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> product </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useProduct</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> addItem </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useCartMutations</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">variantId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> setVariantId</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token generic-function function" style="color:#d73a49">useState</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name builtin">string</span><span class="token generic-function generic class-name"> </span><span class="token generic-function generic class-name operator" style="color:#393A34">|</span><span class="token generic-function generic class-name"> </span><span class="token generic-function generic class-name keyword null nil" style="color:#00009f">null</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword null nil" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// variante escolhida (ou a default/primeira quando o produto chega)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> selected </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useMemo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">product</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword nil" style="color:#00009f">undefined</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> product</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">variants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">find</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">v</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">id</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">===</span><span class="token plain"> variantId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token operator" style="color:#393A34">??</span><span class="token plain"> product</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">variants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">find</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">v</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">isDefault</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token operator" style="color:#393A34">??</span><span class="token plain"> product</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">variants</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">product</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> variantId</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleAdd</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">product </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">selected</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  addItem</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">mutate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      variantId</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> selected</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      quantity</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> selected</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">label</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation">product</span><span class="token template-string interpolation punctuation" style="color:#393A34">.</span><span class="token template-string interpolation property-access">name</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string string" style="color:#e3116c"> (</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation">selected</span><span class="token template-string interpolation punctuation" style="color:#393A34">.</span><span class="token template-string interpolation property-access">label</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string string" style="color:#e3116c">)</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> product</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      unitPrice</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> selected</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">price</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// dado local que o otimismo precisa</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token function-variable function" style="color:#d73a49">onSuccess</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> navigation</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">navigate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'Cart'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="bloco-2--usecart-dependente-de-login">Bloco 2 — <code>useCart()</code> dependente de login<a href="https://docs.mockmerce.com.br/diario/semana-02-tanstack-query#bloco-2--usecart-dependente-de-login" class="hash-link" aria-label="Link direto para bloco-2--usecart-dependente-de-login" title="Link direto para bloco-2--usecart-dependente-de-login" translate="no">​</a></h3>
<p>A rota <code>/cart</code> exige o token do comprador — então a query só dispara <strong>logado</strong>
(<code>enabled: isLoggedIn</code>).</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">src/hooks/useCart.ts</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> useQuery </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@tanstack/react-query'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> getCart </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@/services/cart'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> queryKeys </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@/lib/queryKeys'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> useSession </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@/session/session'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useCart</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> isLoggedIn </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useSession</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useQuery</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    queryKey</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> queryKeys</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">cart</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">all</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    queryFn</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> getCart</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    enabled</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> isLoggedIn</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// sem login não roda (evita 401)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="bloco-3--usecartmutations-com-atualização-otimista">Bloco 3 — <code>useCartMutations</code> com atualização otimista<a href="https://docs.mockmerce.com.br/diario/semana-02-tanstack-query#bloco-3--usecartmutations-com-atualiza%C3%A7%C3%A3o-otimista" class="hash-link" aria-label="Link direto para bloco-3--usecartmutations-com-atualização-otimista" title="Link direto para bloco-3--usecartmutations-com-atualização-otimista" translate="no">​</a></h3>
<p>O coração da semana. As três mutations (adicionar, mudar quantidade, remover) seguem o
mesmo ciclo <code>onMutate</code> → <code>onError</code> → <code>onSettled</code>. Repare no <code>cancelQueries</code>, na <strong>foto</strong>
(<code>previous</code>) e no <code>setQueryData</code> com um objeto <strong>novo</strong> (imutabilidade).</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">src/hooks/useCartMutations.ts</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> useMutation</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> useQueryClient </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@tanstack/react-query'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> addCartItem</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> removeCartItem</span><span class="token imports punctuation" style="color:#393A34">,</span><span class="token imports"> updateCartItem </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@/services/cart'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:#393A34">{</span><span class="token imports"> queryKeys </span><span class="token imports punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@/lib/queryKeys'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">type</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token maybe-class-name">Cart</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@/types/api'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">EMPTY_CART</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token maybe-class-name">Cart</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'optimistic'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> items</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> total</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> itemCount</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token doc-comment comment" style="color:#999988;font-style:italic">/** Recalcula total e itemCount a partir dos itens (mantém o Cart coerente). */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">recompute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">items</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token maybe-class-name">Cart</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">'items'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token maybe-class-name">Cart</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> total </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> items</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">reduce</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sum</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> it</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> sum </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> it</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">subtotal</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> itemCount </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> items</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">reduce</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sum</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> it</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> sum </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> it</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">quantity</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">EMPTY_CART</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> items</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> total</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> itemCount </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useCartMutations</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> queryClient </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useQueryClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> queryKeys</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">cart</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">all</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// rollback + reconciliação, reaproveitados pelas 3 mutations</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#d73a49">rollbackOnError</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">_e</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">unknown</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> _v</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">unknown</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ctx</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> previous</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token maybe-class-name">Cart</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword control-flow" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ctx</span><span class="token operator" style="color:#393A34">?.</span><span class="token plain">previous</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> queryClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">setQueryData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ctx</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">previous</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#d73a49">settle</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> queryClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">invalidateQueries</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> queryKey</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> key </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// Adicionar — precisa de name/unitPrice para DESENHAR o item otimista</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> addItem </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useMutation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function-variable function" style="color:#d73a49">mutationFn</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">v</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> variantId</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> quantity</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">number</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> unitPrice</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">number</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token function" style="color:#d73a49">addCartItem</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">variantId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">quantity</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onMutate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">v</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> queryClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">cancelQueries</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> queryKey</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> key </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic">// 1. trava buscas em voo</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> previous </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> queryClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token generic-function function" style="color:#d73a49">getQueryData</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name maybe-class-name">Cart</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 2. foto do cache</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> base </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> previous </span><span class="token operator" style="color:#393A34">??</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">EMPTY_CART</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> existing </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> base</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">items</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">find</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">it</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> it</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">variantId</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">===</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">variantId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> items </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> existing</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> base</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">items</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">it</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            it</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">variantId</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">===</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">variantId</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token spread operator" style="color:#393A34">...</span><span class="token plain">it</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> quantity</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> it</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">quantity</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">quantity</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> subtotal</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> it</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">unitPrice</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">it</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">quantity</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">quantity</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> it</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token spread operator" style="color:#393A34">...</span><span class="token plain">base</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">items</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            variantId</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">variantId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> sku</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">''</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            unitPrice</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">unitPrice</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> quantity</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">quantity</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> subtotal</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">unitPrice</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">quantity</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      queryClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token generic-function function" style="color:#d73a49">setQueryData</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name maybe-class-name">Cart</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">recompute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">items</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 3. otimismo</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> previous </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">                                    </span><span class="token comment" style="color:#999988;font-style:italic">// 4. contexto p/ rollback</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    onError</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> rollbackOnError</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    onSettled</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> settle</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// Mudar quantidade (0 remove)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> setQuantity </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useMutation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function-variable function" style="color:#d73a49">mutationFn</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">v</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> variantId</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> quantity</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">number</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">updateCartItem</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">variantId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">quantity</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onMutate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">v</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> queryClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">cancelQueries</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> queryKey</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> key </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> previous </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> queryClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token generic-function function" style="color:#d73a49">getQueryData</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name maybe-class-name">Cart</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> base </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> previous </span><span class="token operator" style="color:#393A34">??</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">EMPTY_CART</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> items </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> base</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">items</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">it</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> it</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">variantId</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">===</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">variantId</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token spread operator" style="color:#393A34">...</span><span class="token plain">it</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> quantity</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">quantity</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> subtotal</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> it</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">unitPrice</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">quantity</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> it</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">it</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> it</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">quantity</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      queryClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token generic-function function" style="color:#d73a49">setQueryData</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name maybe-class-name">Cart</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">recompute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">items</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> previous </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    onError</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> rollbackOnError</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    onSettled</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> settle</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// Remover item</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> removeItem </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useMutation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function-variable function" style="color:#d73a49">mutationFn</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">variantId</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">removeCartItem</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">variantId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onMutate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">variantId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword control-flow" style="color:#00009f">await</span><span class="token plain"> queryClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">cancelQueries</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> queryKey</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> key </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> previous </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> queryClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token generic-function function" style="color:#d73a49">getQueryData</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name maybe-class-name">Cart</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> base </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> previous </span><span class="token operator" style="color:#393A34">??</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">EMPTY_CART</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> items </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> base</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">items</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">it</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> it</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">variantId</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!==</span><span class="token plain"> variantId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      queryClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token generic-function function" style="color:#d73a49">setQueryData</span><span class="token generic-function generic class-name operator" style="color:#393A34">&lt;</span><span class="token generic-function generic class-name maybe-class-name">Cart</span><span class="token generic-function generic class-name operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">recompute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">items</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> previous </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    onError</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> rollbackOnError</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    onSettled</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> settle</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> addItem</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> setQuantity</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> removeItem </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p><strong>O entregável do dia é o rollback:</strong> com o backend fora, adicionar um item mostra ele na
hora e depois o <strong>remove</strong> sozinho (o <code>onError</code> restaura a foto). Isso é honestidade de UI.</p>
<div class="theme-admonition theme-admonition-danger admonition_xJq3 alert alert--danger"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>Os 4 erros que mais aparecem aqui</div><div class="admonitionContent_BuS1"><ul>
<li class="">Esquecer <code>await cancelQueries</code> no <code>onMutate</code> → uma busca em voo chega depois e apaga o otimismo.</li>
<li class="">Não retornar <code>{ previous }</code> → o <code>onError</code> não tem o que restaurar.</li>
<li class="">Mutar o array do cache (<code>items.push</code>) em vez de criar um novo → React não re-renderiza.</li>
<li class="">Otimismo sem <code>name</code>/<code>unitPrice</code> → o item aparece "quebrado".</li>
</ul></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="lembretes-de-api">Lembretes de API<a href="https://docs.mockmerce.com.br/diario/semana-02-tanstack-query#lembretes-de-api" class="hash-link" aria-label="Link direto para Lembretes de API" title="Link direto para Lembretes de API" translate="no">​</a></h2>
<ul>
<li class=""><strong>Base (nuvem):</strong> <code>https://api.mockmerce.com.br/v1</code> — os apps conectam no backend na
nuvem, não em <code>localhost</code>. Swagger em <code>https://api.mockmerce.com.br/docs</code>.</li>
<li class="">Headers sempre: <code>X-API-Key</code> (grupo) e <code>X-Student-RM</code> (rastreio). Rotas de comprador exigem
também <code>Authorization: Bearer</code>.</li>
<li class=""><strong>Unidade vendável = variante.</strong> Carrinho/checkout usam <code>variantId</code>; preço/estoque vivem em
<code>variants[]</code>.</li>
</ul>]]></content>
        <author>
            <name>Professor · 2TDSPG</name>
        </author>
        <category label="React Native" term="React Native"/>
        <category label="TanStack Query" term="TanStack Query"/>
        <category label="Semana 2" term="Semana 2"/>
        <category label="Exercícios" term="Exercícios"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Semana 3 · Segunda — Checkout e Pedidos: fechar a compra de ponta a ponta]]></title>
        <id>https://docs.mockmerce.com.br/diario/semana-03-checkout-pedidos</id>
        <link href="https://docs.mockmerce.com.br/diario/semana-03-checkout-pedidos"/>
        <updated>2026-08-17T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Hoje começamos a Semana 3 — Checkout e Pedidos. Até agora o app enchia o carrinho e]]></summary>
        <content type="html"><![CDATA[<p>Hoje começamos a <strong>Semana 3 — Checkout e Pedidos</strong>. Até agora o app enchia o carrinho e
parava num "Finalizar" que não fazia nada. Nesta semana ele passa a <strong>deixar comprar</strong>:
checkout → pagamento (simulado) → pedido → histórico. É o pedaço que faltava para o app ser
"de ponta a ponta" — o coração do <strong>CP1</strong>.</p>
<blockquote>
<p><strong>A frase da semana:</strong> otimismo é pra micro-interação, <strong>não pra dinheiro</strong>. O carrinho a
gente pinta na hora; o pagamento a gente <strong>espera</strong> o servidor confirmar.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="parte-a--a-auth-que-já-veio-pronta-leitura-rápida">Parte A — a auth que já veio pronta (leitura rápida)<a href="https://docs.mockmerce.com.br/diario/semana-03-checkout-pedidos#parte-a--a-auth-que-j%C3%A1-veio-pronta-leitura-r%C3%A1pida" class="hash-link" aria-label="Link direto para Parte A — a auth que já veio pronta (leitura rápida)" title="Link direto para Parte A — a auth que já veio pronta (leitura rápida)" translate="no">​</a></h2>
<p>O app já abre numa tela de <strong>Login</strong> e tem uma <strong>guarda de rotas</strong>. Isso não é o conteúdo
novo — mas entenda o chão em que pisamos. A guarda troca o app inteiro conforme o estado:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">App.tsx</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color:#d73a49">RootNavigator</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> isLoggedIn </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useSession</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> isLoggedIn </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">AppFlow</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">AuthFlow</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// logado vê a loja; deslogado vê login</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>As telas de login <strong>não</strong> chamam <code>navigation.navigate</code> ao dar certo — elas mudam o estado
(<code>isLoggedIn</code>), o React re-renderiza e o stack certo aparece sozinho.</p>
<blockquote>
<p><strong>A ideia que volta o semestre todo:</strong> quem manda na navegação é o <strong>estado</strong>, não o botão.
O login usa o backend (<code>/auth/login</code>, <code>/auth/register</code>) e guarda o token na sessão.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="parte-b--o-fluxo-de-compra">Parte B — o fluxo de compra<a href="https://docs.mockmerce.com.br/diario/semana-03-checkout-pedidos#parte-b--o-fluxo-de-compra" class="hash-link" aria-label="Link direto para Parte B — o fluxo de compra" title="Link direto para Parte B — o fluxo de compra" translate="no">​</a></h2>
<p>Duas ideias no quadro:</p>
<ul>
<li class=""><strong>Máquina de estados do pedido:</strong> <code>PENDING → PAID</code> (pagou) ou <code>PENDING → CANCELLED</code>
(cancelou). O backend é o dono do estado; o app dispara transições e mostra.</li>
<li class=""><strong>Otimismo × confirmação real:</strong> no carrinho fomos otimistas (Semana 2). <strong>Pagar é
diferente</strong> — a gente espera a resposta.</li>
</ul>
<!-- -->
<p>As rotas que usamos:</p>
<table><thead><tr><th>Ação</th><th>Rota</th></tr></thead><tbody><tr><td>Criar pedido do carrinho</td><td><code>POST /orders/checkout</code></td></tr><tr><td>Pagar (simulado)</td><td><code>POST /orders/:id/pay</code> — <code>{ method, simulate }</code></td></tr><tr><td>Histórico / detalhe</td><td><code>GET /orders</code> · <code>GET /orders/:id</code></td></tr><tr><td>Linha do tempo</td><td><code>GET /orders/:id/timeline</code></td></tr><tr><td>Cancelar pendente</td><td><code>POST /orders/:id/cancel</code></td></tr></tbody></table>
<p><code>method</code> ∈ <code>PIX | CREDIT_CARD | BOLETO</code>; <code>simulate</code> ∈ <code>approve | decline</code> (para ver os dois
caminhos). No <strong>item do pedido</strong> o nome vem em <code>productName</code> (no carrinho é <code>name</code>).</p>
<p>E a diferença que define a semana — o pagamento <strong>não</strong> é otimista:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">src/hooks/useOrderActions.ts (resumo)</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#d73a49">usePayOrder</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useMutation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function-variable function" style="color:#d73a49">mutationFn</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">v</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">payOrder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">method</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> v</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">simulate</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function-variable function" style="color:#d73a49">onSuccess</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">order</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">                 </span><span class="token comment" style="color:#999988;font-style:italic">// a RESPOSTA é a verdade; escreve no cache</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    queryClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">setQueryData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">queryKeys</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">orders</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">detail</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">order</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> order</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    queryClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">invalidateQueries</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> queryKey</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> queryKeys</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">orders</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">list</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="mão-na-massa-em-aula">Mão na massa (em aula)<a href="https://docs.mockmerce.com.br/diario/semana-03-checkout-pedidos#m%C3%A3o-na-massa-em-aula" class="hash-link" aria-label="Link direto para Mão na massa (em aula)" title="Link direto para Mão na massa (em aula)" translate="no">​</a></h2>
<p>Começamos pelo <strong>lado da leitura</strong> (mais fácil): <code>src/services/orders.ts</code> + as queries
(<code>useOrders</code>/<code>useOrder</code>/<code>useOrderTimeline</code>) + a tela de <strong>histórico</strong> (<code>OrdersScreen</code>) e o
botão <strong>Pedidos</strong> na lista. Meta mínima: abrir a tela <strong>Pedidos</strong> e ver a lista (vazia no
começo — normal). Erro nº 1: usar <code>name</code> no item do pedido (é <code>productName</code>). Erro nº 2:
esquecer o <code>enabled</code>/login na query → <strong>401</strong>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="-dever-de-casa-segunda--quarta--50-min">📌 Dever de casa (segunda → quarta) · ~50 min<a href="https://docs.mockmerce.com.br/diario/semana-03-checkout-pedidos#-dever-de-casa-segunda--quarta--50-min" class="hash-link" aria-label="Link direto para 📌 Dever de casa (segunda → quarta) · ~50 min" title="Link direto para 📌 Dever de casa (segunda → quarta) · ~50 min" translate="no">​</a></h2>
<p>Entregar no <strong>início da aula de quarta (19/08)</strong>. No app do seu grupo, consumindo a API da
turma. Use o <code>X-Student-RM</code> de <strong>quem está codando</strong>.</p>
<ol>
<li class=""><strong><code>src/services/orders.ts</code></strong> — <code>checkout</code>, <code>listOrders</code>, <code>getOrder</code>, <code>payOrder</code>,
<code>cancelOrder</code>, <code>getOrderTimeline</code>.</li>
<li class=""><strong>Tipos</strong> (<code>Order</code>, <code>OrderItem</code> com <code>productName</code>, <code>Payment</code>, <code>TimelineEntry</code>,
<code>PaymentMethod</code>) e <strong>query keys</strong> de <code>orders</code> + <code>statusLabel</code>/<code>statusColor</code>.</li>
<li class=""><strong>Queries</strong> (<code>useOrders</code>, <code>useOrder</code>, <code>useOrderTimeline</code>) + <strong><code>OrdersScreen</code></strong> (histórico)
com botão <strong>Pedidos</strong> na lista.</li>
<li class=""><strong>Responda em 2 linhas no README:</strong> por que a query de pedidos precisa de <code>enabled</code> ligado
ao login?</li>
</ol>
<p><strong>Critério de pronto:</strong> dá para abrir <strong>Pedidos</strong> e ver a lista (vazia é ok).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="quarta-é-cronometrado-">Quarta é cronometrado 🕒<a href="https://docs.mockmerce.com.br/diario/semana-03-checkout-pedidos#quarta-%C3%A9-cronometrado-" class="hash-link" aria-label="Link direto para Quarta é cronometrado 🕒" title="Link direto para Quarta é cronometrado 🕒" translate="no">​</a></h2>
<p>Venham com o histórico já lendo — vamos fechar a compra em três blocos:</p>
<ol>
<li class=""><strong>Checkout:</strong> <code>useCheckout</code> + <code>CheckoutScreen</code>. No sucesso, <strong>invalide o carrinho</strong>
(esvaziou) e vá ao pedido com <code>navigation.replace</code>.</li>
<li class=""><strong>Pagamento (entregável):</strong> <code>usePayOrder</code> + a seção de pagamento na <code>OrderScreen</code> —
método, alternar <strong>aprovar/recusar</strong>, sem otimismo. Trate o caminho <strong>recusado</strong> (segue
PENDING, não é "deu erro").</li>
<li class=""><strong>Pontas:</strong> linha do tempo, <strong>cancelar</strong> pendente, e a fiação (<code>Cart → Checkout</code>,
<code>Pedidos → Orders</code>, telas no <code>App.tsx</code>).</li>
</ol>
<p><strong>Prova de entrega:</strong> print/gravação de (a) compra até <strong>PAID</strong>, (b) caminho <strong>recusado</strong>
tratado, (c) histórico + linha do tempo.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="lembretes-de-api">Lembretes de API<a href="https://docs.mockmerce.com.br/diario/semana-03-checkout-pedidos#lembretes-de-api" class="hash-link" aria-label="Link direto para Lembretes de API" title="Link direto para Lembretes de API" translate="no">​</a></h2>
<ul>
<li class=""><strong>Base (nuvem):</strong> <code>https://api.mockmerce.com.br/v1</code>. Swagger em
<code>https://api.mockmerce.com.br/docs</code>.</li>
<li class="">Headers sempre: <code>X-API-Key</code> (grupo) e <code>X-Student-RM</code> (rastreio). Rotas de comprador exigem
também <code>Authorization: Bearer</code>.</li>
<li class=""><strong>Unidade vendável = variante.</strong> O pedido nasce do carrinho (<code>variantId</code>); no item do
pedido o nome é <code>productName</code>.</li>
<li class="">Carrinho vazio no checkout → <strong>422</strong>. Pagar pedido que não está PENDING → <strong>409</strong>.</li>
</ul>]]></content>
        <author>
            <name>Professor · 2TDSPG</name>
        </author>
        <category label="React Native" term="React Native"/>
        <category label="Pedidos" term="Pedidos"/>
        <category label="Semana 3" term="Semana 3"/>
        <category label="Exercícios" term="Exercícios"/>
    </entry>
</feed>