🧩 Exercícios Práticos: Context API e Criação de Custom Hooks

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


🎯 Nível 1: Fundamentos

Problema 08.1 — Criação de Contexto Tipado com createContext

Contexto: Criação de Contexto Tipado com createContext no contexto de Context API e Criação de Custom Hooks.

Requisitos de Execução:

  1. Criar ThemeContext com valores light e dark e função de alternância toggleTheme.

Resultado Esperado

Contexto de tema criado e tipado com TypeScript.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_08_1_SeuNome
  2. Envie na tarefa: Atividade Cap 08 - Context API e Criação de Custom Hooks
🔑 Gabarito de Código & Solução Comentada
// ThemeContext.tsx
import React, { createContext, useState, ReactNode } from 'react';

type Theme = 'light' | 'dark';
interface ThemeContextType { theme: Theme; toggleTheme: () => void; }

export const ThemeContext = createContext<ThemeContextType | undefined>(undefined);

export const ThemeProvider = ({ children }: { children: ReactNode }) => {
  const [theme, setTheme] = useState<Theme>('light');
  const toggleTheme = () => setTheme(t => t === 'light' ? 'dark' : 'light');
  return <ThemeContext.Provider value={{ theme, toggleTheme }}>{children}</ThemeContext.Provider>;
};

🔍 Nível 2: Prática

Problema 08.2 — Custom Hook useTheme com Validação Defensiva

Contexto: Custom Hook useTheme com Validação Defensiva no contexto de Context API e Criação de Custom Hooks.

Requisitos de Execução:

  1. Criar hook useTheme() que lance exceção explicativa se usado fora de um <ThemeProvider>.

Resultado Esperado

Hook consumido no componente de toggle de tema.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_08_2_SeuNome
  2. Envie na tarefa: Atividade Cap 08 - Context API e Criação de Custom Hooks
🔑 Gabarito de Código & Solução Comentada
// useTheme.ts
import { useContext } from 'react';
import { ThemeContext } from './ThemeContext';

export const useTheme = () => {
  const context = useContext(ThemeContext);
  if (!context) {
    throw new Error('useTheme deve ser utilizado dentro de um <ThemeProvider>');
  }
  return context;
};

⚡ Nível 3: Integração

Problema 08.3 — Custom Hook useLocalStorage com Sincronização entre Abas

Contexto: Custom Hook useLocalStorage com Sincronização entre Abas no contexto de Context API e Criação de Custom Hooks.

Requisitos de Execução:

  1. Implementar hook useLocalStorage(key, initialValue) escutando eventos de storage do navegador.

Resultado Esperado

Dados sincronizados no LocalStorage e atualizados automaticamente entre abas.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_08_3_SeuNome
  2. Envie na tarefa: Atividade Cap 08 - Context API e Criação de Custom Hooks
🔑 Gabarito de Código & Solução Comentada
// useLocalStorage.ts
import { useState, useEffect } from 'react';

export function useLocalStorage<T>(key: string, initial: T) {
  const [value, setValue] = useState<T>(() => {
    const saved = localStorage.getItem(key);
    return saved ? JSON.parse(saved) : initial;
  });

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  return [value, setValue] as const;
}

🏆 Nível 4: Desafio Corporativo

Problema 08.4 — Separação de Contextos de Estado e Despacho para Evitar Re-renders

Contexto: Separação de Contextos de Estado e Despacho para Evitar Re-renders no contexto de Context API e Criação de Custom Hooks.

Requisitos de Execução:

  1. Dividir AuthContext em AuthStateContext e AuthDispatchContext otimizando a árvore de componentes.

Resultado Esperado

Re-renderizações desnecessárias eliminadas em componentes que apenas disparam ações.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_08_4_SeuNome
  2. Envie na tarefa: Atividade Cap 08 - Context API e Criação de Custom Hooks
🔑 Gabarito de Código & Solução Comentada
// SplitContext.tsx
import React, { createContext, useContext, useReducer, ReactNode } from 'react';

const StateCtx = createContext<any>(null);
const DispatchCtx = createContext<any>(null);

export const SplitProvider = ({ children }: { children: ReactNode }) => {
  const [state, dispatch] = useReducer((s: any) => s, {});
  return (
    <StateCtx.Provider value={state}>
      <DispatchCtx.Provider value={dispatch}>{children}</DispatchCtx.Provider>
    </StateCtx.Provider>
  );
};