React Build Resolver
NovaPulse SaaS — Next.js 14 App Router · TypeScript · Tailwind
✓ Build Resuelto
4
Errores detectados
4
Errores corregidos
5
Archivos modificados
1
Dep. instalada
Build Status: SUCCESS
Errors Fixed: 4  |  Files Modified: DashboardFilters.tsx, MetricsChart.tsx, ExportButton.tsx, exportData.ts, tsconfig.json  |  Dep instalada: @types/react@18
next build
47.2 s
Detección del bundler
Terminal — diagnóstico inicial
[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
next build — producción
[ 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.