Files
novi-lessons/v2/Les03-Cursor-Basics/Les03-Debug-Challenge-Hard-ANTWOORDEN.md
2026-02-27 13:56:19 +01:00

9.8 KiB
Raw Blame History

Debug Challenge HARD - Antwoordenblad (ALLEEN VOOR TIM)

⚠️ NIET DELEN MET STUDENTEN


Overzicht

Dit project is aanzienlijk complexer dan de easy versie. Het bevat:

  • Blog met dynamische routes
  • Dashboard met statistieken
  • API route voor quotes
  • Utility functions
  • TypeScript types

12 fouten verspreid over 4 categorieën:

  • Blokkerende fouten (compile/runtime)
  • Logische fouten (code draait maar werkt verkeerd)
  • Pattern fouten (React anti-patterns)
  • Styling fouten (inline styles + custom CSS → Tailwind)

Geschatte tijd: 2-3 uur met AI


CATEGORIE 1: BLOKKERENDE FOUTEN

Fout 1: Missing dependency — clsx

Bestand: lib/utils.ts (regel 2) Symptoom:

Module not found: Can't resolve 'clsx'

Oorzaak: clsx wordt geïmporteerd maar staat niet in package.json. formatDate() wordt overal gebruikt, dus dit blokkeert ALLES.

Fix:

npm install clsx

Moeilijkheid: (makkelijk, zelfde als easy versie)


Fout 2: Verkeerde import path — NextResponse

Bestand: app/api/quotes/route.ts (regel 2) Symptoom:

Module not found: Can't resolve 'next/servers'

Oorzaak: "next/servers" moet "next/server" zijn (zonder s).

Fix:

// FOUT:
import { NextResponse } from "next/servers";

// CORRECT:
import { NextResponse } from "next/server";

Moeilijkheid: (subtiel — 1 letter verschil)


CATEGORIE 2: LOGISCHE FOUTEN

Fout 3: Array.slice() met verkeerde parameters

Bestand: components/BlogPreview.tsx (regel 7) Symptoom: BlogPreview sectie op homepage toont GEEN posts (lege grid)

Oorzaak: blogPosts.slice(-2, 0) retourneert een lege array. slice(-2, 0) betekent: start bij index -2 (2e van achteren), stop bij index 0 — dat is leeg!

Fix:

// FOUT:
const recentPosts = blogPosts.slice(-2, 0);

// CORRECT:
const recentPosts = blogPosts.slice(0, 2);

Moeilijkheid: (geen error, gewoon lege output — student moet debuggen WAAROM)


Fout 4: Icon mapping mist "star" entry

Bestand: app/dashboard/page.tsx (regel 25-30) Symptoom: De "Rating" stat card toont geen icon (undefined rendered als leeg)

Oorzaak: getIcon() functie heeft entries voor "users", "eye", "clock" maar NIET voor "star". De stats array bevat wel icon: "star".

Fix:

function getIcon(iconName: string) {
  const icons: Record<string, React.ReactNode> = {
    users: <Users size={24} />,
    eye: <Eye size={24} />,
    clock: <Clock size={24} />,
    star: <Star size={24} />,  // ← TOEVOEGEN
  };
  return icons[iconName];
}

Moeilijkheid: (geen crash, subtiel visueel verschil)


Fout 5: Mobile menu altijd verborgen

Bestand: components/Header.tsx (regel 62 + 73) Symptoom: Hamburger menu knop is onzichtbaar, en zelfs als je display: none verwijdert van de button, is het dropdown menu ALSOOK display: none.

Oorzaak: Twee problemen:

  1. De hamburger button heeft display: 'none' → onzichtbaar
  2. Het mobile menu div heeft display: 'none' → zelfs als menuOpen true is

Fix: Dit moet volledig naar responsive Tailwind met md:hidden/md:flex:

// Button: verberg op desktop, toon op mobiel
<button className="md:hidden" ...>

// Desktop nav: verberg op mobiel
<nav className="hidden md:flex gap-6" ...>

// Mobile menu: toon als flex wanneer open
{menuOpen && (
  <div className="flex flex-col md:hidden p-3 border-t bg-white">

Moeilijkheid: (vereist begrijpen van responsive design patterns)


CATEGORIE 3: REACT PATTERN FOUTEN

Fout 6: async functie in useEffect

Bestand: app/dashboard/page.tsx (regel 35-39) Symptoom: React warning in console:

Warning: useEffect must not return anything besides a function

En mogelijke infinite loop.

Oorzaak: useEffect(async () => {...}) is een React anti-pattern. async functie retourneert een Promise, maar useEffect verwacht void of een cleanup functie.

Fix:

// FOUT:
useEffect(async () => {
  const res = await fetch("/api/quotes");
  ...
}, [quote]);

// CORRECT:
useEffect(() => {
  async function fetchQuote() {
    const res = await fetch("/api/quotes");
    const data = await res.json();
    setQuote(data.text);
    setLoading(false);
  }
  fetchQuote();
}, []);  // ← ook dependency array gefixed (zie Fout 7)

Moeilijkheid: (vereist kennis van React hooks patterns)


Fout 7: Verkeerde dependency array → infinite loop

Bestand: app/dashboard/page.tsx (regel 39) Symptoom: Dashboard pagina loopt vast, continue fetch requests in Network tab

Oorzaak: [quote] als dependency betekent: "run opnieuw als quote verandert". Maar de effect ZET quote, wat de effect OPNIEUW triggert → infinite loop.

Fix:

// FOUT:
}, [quote]);

// CORRECT:
}, []);  // Lege array = run 1x bij mount

Moeilijkheid: (vereist begrip van useEffect dependency arrays)


Fout 8: Null check mist op quote state

Bestand: components/QuoteOfTheDay.tsx (regel 22) Symptoom: TypeError: Cannot read properties of null (reading 'text')

Oorzaak: quote begint als null, maar zodra loading false is, probeert de component quote.text te lezen. Als de API fails of traag is, kan dit crashen.

Fix: Voeg TypeScript type toe en null check:

// Verbeterde state typing:
const [quote, setQuote] = useState<{ text: string; author: string } | null>(null);

// In de render:
{!loading && quote && (
  <>
    <blockquote>"{quote.text}"</blockquote>
    <cite> {quote.author}</cite>
  </>
)}

Moeilijkheid: (runtime error, maar duidelijke error message)


CATEGORIE 4: STYLING FOUTEN (Inline Styles → Tailwind)

Fout 9: Custom CSS classes in globals.css

Bestand: app/globals.css Probleem: .card, .page-container, .section-title zijn custom CSS classes. Deze horen Tailwind utility classes te zijn.

Fix: Verwijder custom CSS uit globals.css. Vervang in alle componenten:

  • .cardclassName="p-6 bg-white rounded-xl border border-gray-200 hover:shadow-lg hover:-translate-y-0.5 transition-all"
  • .page-containerclassName="max-w-[1200px] mx-auto px-5"
  • .section-titleclassName="text-3xl font-bold text-center mb-10 text-gray-900"

Moeilijkheid: (moet begrijpen waarom Tailwind beter is dan custom CSS)


Fout 10-12: Inline styles in alle componenten

Bestanden met inline styles:

# Bestand Complexiteit
10 components/Hero.tsx Hoog (gradient, positioning)
11 components/Header.tsx Hoog (responsive, sticky)
12 components/Footer.tsx Medium (grid, links)
- components/StatsSection.tsx Medium (grid)
- components/BlogPreview.tsx Medium (grid, cards)
- components/QuoteOfTheDay.tsx Laag
- app/blog/page.tsx Medium (grid, tags)
- app/blog/[slug]/page.tsx Medium (article layout)
- app/dashboard/page.tsx Hoog (stats grid, cards)

Studenten moeten minimaal 3-4 bestanden omzetten.

Aanpak:

  1. Selecteer inline style code
  2. Ctrl+K → "Converteer inline styles naar Tailwind CSS. Gebruik de brand- kleuren uit tailwind.config.ts waar mogelijk."
  3. Review + Accept

Moeilijkheid: per bestand (maar het zijn er VEEL)


Samenvatting Alle Fouten

# Type Bestand Ernst Moeilijkheid
1 Missing dependency (clsx) lib/utils.ts 🔴 Blokkerend
2 Verkeerde import (next/servers) api/quotes/route.ts 🔴 Blokkerend
3 Verkeerde slice() params BlogPreview.tsx 🟡 Logisch
4 Missende icon mapping dashboard/page.tsx 🟡 Logisch
5 Mobile menu altijd hidden Header.tsx 🟡 Logisch
6 async in useEffect dashboard/page.tsx 🟠 Anti-pattern
7 Infinite loop dep array dashboard/page.tsx 🔴 Runtime crash
8 Null check quote state QuoteOfTheDay.tsx 🔴 Runtime crash
9 Custom CSS → Tailwind globals.css 🟡 Styling
10-12 Inline styles (9+ bestanden) Overal 🟡 Styling elk

Verwachte Oplos-Volgorde

  1. npm install → werkt
  2. npm run devCan't resolve 'clsx'npm install clsx
  3. npm run devCan't resolve 'next/servers' → fix import
  4. Site laadt! Maar:
    • BlogPreview is leeg → fix slice()
    • Dashboard crasht/loopt vast → fix useEffect + dep array
    • Quote component crasht → fix null check
    • Rating icon mist → fix icon mapping
    • Mobile menu werkt niet → fix responsive
  5. Inline styles → Tailwind conversie
  6. Custom CSS → Tailwind refactor

Verwacht Request Gebruik

Actie Requests
Debug blokkerende errors (Chat) 2-3
Fix logische fouten (Chat + Edit) 3-4
Fix React patterns (Chat) 2-3
Inline styles → Tailwind (Inline Edit × 4-5) 4-5
Totaal 11-15 requests

⚠️ Dit is meer dan de easy versie. Studenten op Hobby plan moeten efficiënt werken. Student plan (500/maand) is ruim voldoende.


Tips voor Tim

  • Dit is echt moeilijk. Fout 5, 6, 7 zijn lastig voor beginners. Verwacht dat studenten hier hulp bij nodig hebben.
  • De useEffect fouten zijn een goed leermoment — dit is een HEEL veelvoorkomende bug in React.
  • De slice() bug is een subtiele logische fout. Studenten moeten leren: "het werkt zonder errors, maar het resultaat klopt niet" → debuggen.
  • Mobile menu is bewust moeilijk. Dit vereist dat ze responsive design begrijpen. Goede Cursor prompt: "Maak deze header responsive met een hamburger menu dat werkt op mobiel met Tailwind."
  • Geef de easy zip als standaard. Hard is voor studenten die de easy versie snel af hebben of die extra uitdaging willen.