4
Errores detectados
4
Errores corregidos
5
Archivos modificados
1
Dep. instalada
Detección del bundler
[detect] next.config.js encontrado → Next.js (App Router) [detect] TypeScript: tsconfig.json presente → modo TSX activo [detect] package.json react: ^18.2.0 react-dom: ^18.2.0 [detect] @types/react: NOT FOUND ← causa del Error 4 [build] $ npm run build [build] ▲ Next.js 14.2.3 [build] Creating an optimized production build... [error] ✘ Failed — 4 errors found. Initiating surgical resolution workflow.
Diagnóstico y correcciones quirúrgicas
1
"use client" faltante en componente con useState
FIXED
DashboardFilters.tsx
Error
You're importing a component that needs useState. It only works in a Client Component but none of its parents are marked with "use client". // DashboardFilters.tsx (antes) import { useState } from 'react'; export function DashboardFilters() { const [filter, setFilter] = useState('7d'); ... }
Fix aplicado
// DashboardFilters.tsx (después) "use client"; ← añadir L1 import { useState } from 'react'; export function DashboardFilters() { const [filter, setFilter] = useState('7d'); ... } // dashboard/page.tsx no cambia: // sigue siendo Server Component
2
Hydration mismatch — valor monetario divergente servidor/cliente
FIXED
MetricsChart.tsx
Error
Hydration failed because the initial UI does not match what was rendered on the server. Text content did not match. Server: "" Client: "€12,450" // MetricsChart.tsx (antes) const revenue = formatCurrency( data.totalRevenue // accede // a localStorage en render ); return <span>{revenue}</span>;
Fix aplicado
import { useState, useEffect } from 'react'; // MetricsChart.tsx (después) const [revenue, setRevenue] = useState(""); // placeholder useEffect(() => { setRevenue( formatCurrency(data.totalRevenue) ); }, [data.totalRevenue]); return <span> {revenue || "—"} // skeleton </span>;
3
Módulo 'fs' importado en componente cliente
FIXED
ExportButton.tsx
Error
Module not found: Can't resolve 'fs' // ExportButton.tsx (antes) // importaba directamente // la utilidad de servidor: import { exportToCSV } from '@/lib/exportData'; // exportData.ts usaba: // import fs from 'fs'; // → bundleado para el cliente // → crash
Fix aplicado
// ExportButton.tsx (después) // Llama al API route en lugar // de importar código de servidor async function handleExport() { const res = await fetch( '/api/export', { method: 'POST', body: JSON.stringify(params) } ); const blob = await res.blob(); downloadBlob(blob, 'export.csv'); } // exportData.ts permanece intacto // solo se consume desde la API route
4
@types/react no instalado — tipos de React ausentes
FIXED
tsconfig.json + package.json
Error
Cannot find module '@types/react' or its corresponding type declarations. // npm ls @types/react // → (empty — not installed) // tsconfig.json (antes) { "compilerOptions": { "jsx": "react", // legacy "moduleResolution": "node" // desactualizado } }
Fix aplicado
$ npm i -D @types/react@18 @types/react-dom@18 // tsconfig.json (después) { "compilerOptions": { "jsx": "react-jsx", // React 17+ "moduleResolution": "bundler", // Next.js 13+ "esModuleInterop": true } } // @types/react major = react major // (18 ↔ 18) ← nunca mezclar
Archivos modificados
| Archivo | Tipo de cambio | Líneas afectadas | Estado |
|---|---|---|---|
| src/components/DashboardFilters.tsx | Añadir "use client" directiva | +1 línea | Fixed |
| src/components/MetricsChart.tsx | Mover cálculo a useEffect | +7 / -3 | Fixed |
| src/components/ExportButton.tsx | Reemplazar import directo por fetch API | +12 / -2 | Fixed |
| tsconfig.json | jsx → react-jsx, moduleResolution → bundler | +3 / -2 | Fixed |
| package.json (devDependencies) | @types/react@18 + @types/react-dom@18 | +2 líneas | Fixed |
Log del build final
[ 0.1s] ✓ @types/react@18.3.3 instalado [ 0.2s] ✓ tsconfig.json validado — jsx: react-jsx, moduleResolution: bundler [ 0.4s] ▲ Next.js 14.2.3 [ 1.2s] ℹ Creating an optimized production build... [ 8.4s] ✓ Compiled successfully [12.0s] ✓ Linting and checking validity of types [18.3s] ✓ Collecting page data [34.7s] ✓ Generating static pages (12/12) [41.5s] ✓ Finalizing page optimization [47.2s] ✓ Build complete — 0 errors, 0 warnings Route (app) Size First Load JS ┌ ○ / 5.2 kB 92.1 kB ├ ○ /dashboard 8.7 kB 95.6 kB ├ ○ /dashboard/analytics 6.4 kB 93.3 kB └ ● /api/export 0 B 0 B + First Load JS shared by all 86.9 kB ├ chunks/framework-64ad19... 44.8 kB └ chunks/main-app-... 42.1 kB
Principios aplicados
Cambios mínimos y quirúrgicos
Solo se tocó lo estrictamente necesario para corregir el error. Sin refactoring no solicitado.
Verificación tras cada fix
Build ejecutado después de cada corrección para confirmar que no se generaron errores nuevos.
Sin @ts-ignore ni disable
Nunca se silenció el compilador. Se corrigió la raíz del problema en cada caso.
Causa raíz sobre síntoma
El import de
fs no se wrapeó ni ocultó — se rearquitecturó el flujo correctamente.RSC boundary respetado
Server Components no convertidos a Client innecesariamente. Solo el componente mínimo afectado.
Versiones alineadas
@types/react@18 instalado al mismo major que react@18. Nunca mezclar majors distintos.