Spec Frontend Com React • Trilha Progressiva em 4 Níveis


🎯 Nível 1: Fundamentos

Problema 04.1 — Sincronização com o DOM e Array de Dependências

Contexto: Sincronização com o DOM e Array de Dependências no contexto de Efeitos Colaterais com useEffect e Cleanup.

Requisitos de Execução:

  1. Atualizar o document.title da página sempre que o contador de notificações for modificado.

Resultado Esperado

Título da aba do navegador sincronizado: '(3) Novas Notificações'.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_04_1_SeuNome
  2. Envie na tarefa: Atividade Cap 04 - Efeitos Colaterais com useEffect e Cleanup
🔑 Gabarito de Código & Solução Comentada
// PageTitleSync.tsx
import React, { useState, useEffect } from 'react';

export const NotificationBadge: React.FC = () => {
  const [unreadCount, setUnreadCount] = useState(3);

  useEffect(() => {
    document.title = unreadCount > 0 ? `(${unreadCount}) Notificações` : 'Portal';
  }, [unreadCount]);

  return <button onClick={() => setUnreadCount(0)}>Marcar lidas</button>;
};

🔍 Nível 2: Prática

Problema 04.2 — Função de Limpeza (Cleanup) com Timers (setInterval)

Contexto: Função de Limpeza (Cleanup) com Timers (setInterval) no contexto de Efeitos Colaterais com useEffect e Cleanup.

Requisitos de Execução:

  1. Implementar cronômetro com setInterval garantindo o cancelamento no cleanup com clearInterval.

Resultado Esperado

Timer em execução | Memória liberada ao desmontar o componente.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_04_2_SeuNome
  2. Envie na tarefa: Atividade Cap 04 - Efeitos Colaterais com useEffect e Cleanup
🔑 Gabarito de Código & Solução Comentada
// TimerCronometro.tsx
import React, { useState, useEffect } from 'react';

export const TimerCronometro: React.FC = () => {
  const [segundos, setSegundos] = useState(0);

  useEffect(() => {
    const timerId = setInterval(() => {
      setSegundos(prev => prev + 1);
    }, 1000);

    return () => clearInterval(timerId); // Cleanup
  }, []);

  return <div>Tempo decorrido: {segundos}s</div>;
};

⚡ Nível 3: Integração

Problema 04.3 — Cancelamento de Requisições HTTP com AbortController

Contexto: Cancelamento de Requisições HTTP com AbortController no contexto de Efeitos Colaterais com useEffect e Cleanup.

Requisitos de Execução:

  1. Disparar busca assíncrona no useEffect e cancelar requisição pendente com controller.abort() caso o usuário digite rápido.

Resultado Esperado

Race conditions de rede evitadas com AbortController.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_04_3_SeuNome
  2. Envie na tarefa: Atividade Cap 04 - Efeitos Colaterais com useEffect e Cleanup
🔑 Gabarito de Código & Solução Comentada
// SearchAutocomplete.tsx
import React, { useState, useEffect } from 'react';

export const SearchAutocomplete: React.FC<{ query: string }> = ({ query }) => {
  const [results, setResults] = useState<string[]>([]);

  useEffect(() => {
    const controller = new AbortController();
    fetch(`/api/search?q=${encodeURIComponent(query)}`, { signal: controller.signal })
      .then(res => res.json())
      .then(data => setResults(data.items))
      .catch(err => { if (err.name !== 'AbortError') console.error(err); });

    return () => controller.abort();
  }, [query]);

  return <ul>{results.map((r, i) => <li key={i}>{r}</li>)}</ul>;
};

🏆 Nível 4: Desafio Corporativo

Problema 04.4 — Diferenciação entre useEffect e useLayoutEffect para Medições do DOM

Contexto: Diferenciação entre useEffect e useLayoutEffect para Medições do DOM no contexto de Efeitos Colaterais com useEffect e Cleanup.

Requisitos de Execução:

  1. Utilizar useLayoutEffect para medir a largura de um elemento antes do paint da tela, prevenindo flicker visual.

Resultado Esperado

Dimensões calculadas sincronamente antes da renderização na tela.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_04_4_SeuNome
  2. Envie na tarefa: Atividade Cap 04 - Efeitos Colaterais com useEffect e Cleanup
🔑 Gabarito de Código & Solução Comentada
// TooltipPosition.tsx
import React, { useState, useRef, useLayoutEffect } from 'react';

export const TooltipPosition: React.FC = () => {
  const elRef = useRef<HTMLDivElement>(null);
  const [width, setWidth] = useState(0);

  useLayoutEffect(() => {
    if (elRef.current) {
      setWidth(elRef.current.getBoundingClientRect().width);
    }
  }, []);

  return <div ref={elRef}>Largura: {width}px</div>;
};