Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

O Problema da Sincronização

O botão RSVP funciona de uma forma limitada: ele muda de texto quando clicado. Vamos expandir um pouco. Cada card agora mostra um contador de confirmações, e clicar no botão incrementa esse contador:

for (const ev of events) {
  // ... (criar título, data, descrição, local como antes)

  let rsvpCount = 0;

  const counter = document.createElement("p");
  counter.textContent = `Confirmações: ${rsvpCount}`;

  const btn = document.createElement("button");
  btn.textContent = "RSVP";
  btn.addEventListener("click", () => {
    rsvpCount++;
    counter.textContent = `Confirmações: ${rsvpCount}`;
  });

  card.append(title, date, desc, location, info, counter, btn);
  container.appendChild(card);
}

Código 6-8: Botão RSVP que incrementa um contador local de confirmações.

Funciona. Clique no botão, o número sobe. Mas agora imagine que a página também mostra um resumo no topo — o total de confirmações de todos os eventos:

const summary = document.createElement("p");
summary.textContent = "Total de confirmações: 0";
document.body.insertBefore(summary, container);

Quando o usuário clica num botão RSVP, o contador daquele card atualiza. Mas o resumo no topo continua mostrando 0. Para atualizá-lo, precisamos encontrar o elemento do resumo e recalcular o total:

btn.addEventListener("click", () => {
  rsvpCount++;
  counter.textContent = `Confirmações: ${rsvpCount}`;

  // Atualizar o resumo no topo
  totalCount++;
  summary.textContent = `Total de confirmações: ${totalCount}`;
});

Dois lugares exibindo o mesmo dado, duas linhas de código para atualizar. Agora adicione um terceiro: um badge no título da página mostrando o total.

btn.addEventListener("click", () => {
  rsvpCount++;
  counter.textContent = `Confirmações: ${rsvpCount}`;

  totalCount++;
  summary.textContent = `Total de confirmações: ${totalCount}`;

  // Atualizar o badge no título
  pageTitle.textContent = `TamoJunto — Eventos (${totalCount})`;
});

Três lugares, três linhas. E se esquecermos um? O dado fica inconsistente — o card mostra 3, o resumo mostra 2, o título mostra 1. O usuário vê números diferentes para a mesma informação. E cada novo lugar que exibir esse dado é mais uma linha que alguém precisa lembrar de adicionar1.

O problema não é que o código está errado. Cada linha individualmente faz o que deve. O problema é que o desenvolvedor está fazendo um trabalho que deveria ser automático: toda vez que um dado muda, todo lugar que exibe esse dado precisa ser atualizado manualmente. A manipulação direta do DOM não oferece nenhum mecanismo para isso.

Essa é a sincronização de estado — o dado (state) e a interface (view) precisam estar em sincronia, e com manipulação direta do DOM, manter essa sincronia é responsabilidade inteiramente do programador.


  1. O contador de RSVP aqui é puramente local — ele existe apenas no JavaScript da página. Nenhuma requisição é enviada ao backend, e recarregar a página zera tudo. Endpoints de escrita (como POST /api/rsvps) só aparecem quando o TamoJunto precisar persistir essas confirmações. ↩