{
  "id": "ai-overuses-useeffect",
  "type": "failures",
  "category": "failures",
  "locale": "fr",
  "url": "/fr/failures/ai-overuses-useeffect",
  "title": "Comment corriger la surutilisation de useEffect par l'IA",
  "description": "Les agents IA utilisent useEffect pour gérer l'état dérivé, les transformations d'événements et la récupération de données qui devraient plutôt utiliser useMemo, les gestionnaires d'événements ou les Server Components.",
  "tools": [
    "Cursor",
    "Claude Code",
    "Codex",
    "Windsurf"
  ],
  "stack": [
    "Next.js",
    "TypeScript"
  ],
  "tags": [
    "react",
    "nextjs",
    "hydration"
  ],
  "difficulty": null,
  "updated": "2026-06-08",
  "markdown": "L'agent encapsule la logique dans `useEffect` qui devrait être un état dérivé, un gestionnaire d'événements ou une récupération par Server Component — provoquant des rendus supplémentaires, des fermetures obsolètes et des conditions de concurrence.\n\n## Le symptôme\n\n`useEffect` est utilisé pour calculer des valeurs dérivées ou synchroniser un état qui pourrait être un simple calcul.\n\n```tsx\n\"use client\";\nimport { useState, useEffect } from \"react\";\n\n// WRONG — useEffect to compute derived state\nexport function CartSummary({ items }: { items: CartItem[] }) {\n  const [total, setTotal] = useState(0);\n\n  useEffect(() => {\n    setTotal(items.reduce((sum, item) => sum + item.price * item.qty, 0));\n  }, [items]);\n\n  return <p>Total: ${total}</p>;\n  // Renders twice: once with total=0, once after the effect runs\n}\n```\n\nUn deuxième modèle : récupérer des données dans `useEffect` alors qu'un Server Component pourrait le faire sans aucun coût de bundle client.\n\n```tsx\n\"use client\";\nuseEffect(() => {\n  fetch(\"/api/products\").then((r) => r.json()).then(setProducts);\n}, []);\n// Waterfall: page loads -> JS executes -> fetch starts -> render\n```\n\n## Pourquoi cela se produit\n\n`useEffect` était la principale échappatoire pour les effets de bord dans React 16/17. Les modèles entraînés sur du code pré-React-18 et pré-App-Router ont appris à l'utiliser par défaut. Le modèle mental \"J'ai besoin que quelque chose se produise après le rendu\" correspond à `useEffect` même lorsque la vraie solution est plus simple.\n\n## Comment le repérer\n\n- `useEffect` définit un état qui est directement calculable à partir des props ou d'un autre état.\n- `useEffect(() => { fetch(...).then(setState) }, [])` en haut d'un composant qui n'est pas dans un arbre Server Component.\n- `useEffect` sans nettoyage dont la dépendance est une fonction (risque de fermeture obsolète).\n- `useEffect` utilisé uniquement pour la journalisation ou l'analyse lors du montage.\n\n## Comment le corriger\n\nUtilisez le bon outil pour la tâche :\n\n```tsx\n// CORRECT — derived state: just compute it\nexport function CartSummary({ items }: { items: CartItem[] }) {\n  const total = items.reduce((sum, item) => sum + item.price * item.qty, 0);\n  return <p>Total: ${total.toFixed(2)}</p>;\n}\n\n// CORRECT — expensive derivation: useMemo\nimport { useMemo } from \"react\";\n\nexport function FilteredList({ items, query }: { items: Item[]; query: string }) {\n  const filtered = useMemo(\n    () => items.filter((i) => i.name.toLowerCase().includes(query.toLowerCase())),\n    [items, query]\n  );\n  return <ul>{filtered.map((i) => <li key={i.id}>{i.name}</li>)}</ul>;\n}\n```\n\n```tsx\n// CORRECT — data fetching: async Server Component (no useEffect needed)\n// app/products/page.tsx\nexport default async function ProductsPage() {\n  const products = await fetch(\"https://api.example.com/products\").then((r) =>\n    r.json()\n  );\n  return <ProductList products={products} />;\n}\n```\n\n```txt\n[ ] Derived values from props/state are plain calculations, not useEffect + setState\n[ ] Expensive derivations use useMemo, not useEffect\n[ ] Data fetching on mount moves to async Server Components or React Query/SWR\n[ ] Event-driven side-effects (form submit, button click) are in event handlers\n[ ] useEffect is reserved for: external system sync, subscriptions, cleanup\n[ ] Every useEffect that sets state has a loading/error state and cleanup\n```\n\n## Prompt de correction\n\n```txt title=\"Fix Prompt\"\nThis component uses useEffect to compute derived state or fetch initial data.\nRefactor it: replace derived-state effects with direct calculations or useMemo,\nmove initial data fetching to an async Server Component parent or to a\ndata-fetching library (SWR/React Query) with proper loading/error handling, and\nkeep useEffect only for genuine external-system synchronization that requires\ncleanup. Explain each useEffect you keep and why it cannot be replaced.\n```\n\n## Test\n\n```bash\n# Count useEffect calls — a high number is a smell worth reviewing\ngrep -rn \"useEffect\" --include=\"*.tsx\" --include=\"*.ts\" src/ app/ \\\n  | grep -v \"node_modules\" \\\n  | wc -l\n\n# Flag useEffect+setState patterns for manual review\ngrep -A5 \"useEffect\" app/**/*.tsx 2>/dev/null | grep \"setState\\|set[A-Z]\" \\\n  && echo \"REVIEW: possible derived-state antipattern\" || echo \"OK\"\n```"
}