Appearance
Reglas de Estructura de Módulos React
Documento complementario: Estructura de Módulos React
Tabla de Decisiones Rápidas
¿Cuándo usar estructura por recurso vs plana?
| Si tu módulo tiene... | Usar |
|---|---|
| 1-2 recursos, < 15 componentes | Estructura plana |
| 3+ recursos, 15+ componentes | Estructura por recurso ⭐ |
| Crecimiento previsto | Estructura por recurso ⭐ |
¿Cuándo crear subcarpeta vs archivo plano?
| Escenario | Solución | Ejemplo |
|---|---|---|
| Componente con 1 archivo | Archivo plano | DisciplinaForm.tsx |
| Componente con 2-3 archivos relacionados | Subcarpeta + index.tsx | MiembroForm/index.tsx |
| Grupo de 3+ modales relacionados | Subcarpeta temática | DisciplinaModals/AddModal.tsx |
| Componente complejo (4+ archivos) | Subcarpeta organizada | MiembroForm/ con utils, types |
¿Cuándo usar index.tsx vs nombre explícito?
| Contexto | Usar | Import resultante |
|---|---|---|
| Componente principal de carpeta | index.tsx | import Form from './MiembroForm' ⭐ |
| Sub-componente en carpeta | Nombre explícito | import { DatosBasicos } from './MiembroForm' |
| Componente standalone | Nombre explícito | import Form from './DisciplinaForm' |
| Múltiples componentes en carpeta | index.tsx + exports | import { A, B } from './Modals' |
Convenciones de Nomenclatura
En Subcarpetas de Componentes
Regla: Eliminar prefijos redundantes cuando el contexto lo da la carpeta.
| Ubicación | ❌ Nombre Antiguo | ✅ Nombre Nuevo | Razón |
|---|---|---|---|
MiembroForm/ | MiembroFormDatosBasicos.tsx | DatosBasicos.tsx | Carpeta ya dice "MiembroForm" |
DisciplinaModals/ | AddMiembroDisciplinaModal.tsx | AddModal.tsx | Carpeta da contexto |
ProductoModals/ | ConfirmDeleteMiembroProductoModal.tsx | DeleteConfirmModal.tsx | Más conciso |
Excepción: Mantener prefijo si hay ambigüedad o si el componente se exporta fuera de su carpeta.
En Hooks
| Tipo de Hook | Ubicación | Nombre |
|---|---|---|
| Query/Mutation principal | {Recurso}/hooks/ | use{Recurso}.ts |
| Lógica de negocio | {Recurso}/hooks/ | use{Recurso}{Feature}.ts |
| Orquestación (modales) | {Recurso}/hooks/ | use{Recurso}{Feature}.ts |
| Sub-recurso relacionado | {Recurso}/hooks/ | use{SubRecurso}.ts |
Ejemplo:
Miembro/hooks/
├── useMiembro.ts # useMiembroList, useCreateMiembro, etc.
├── useMiembroFormLogic.ts # Lógica específica del formulario
├── useMiembroFormModals.ts # Orquestación de modales
├── useMiembroDisciplina.ts # Sub-recurso disciplinas
└── useMiembroProducto.ts # Sub-recurso productosEn Services/Schemas/Types
Regla: Mirror Pattern - Reflejar la estructura de componentes.
Miembro/
├── components/
│ ├── MiembroForm/
│ └── DisciplinaModals/
│
├── services/
│ ├── miembro.service.ts # ← Para MiembroForm
│ └── miembroDisciplina.service.ts # ← Para DisciplinaModals
│
├── schemas/
│ ├── miembro.schema.ts
│ └── miembroDisciplina.schema.ts
│
└── types/
├── miembro.types.ts
└── miembroDisciplina.types.tsPatrones de Import
Imports dentro del mismo recurso
typescript
// Miembro/components/MiembroForm/index.tsx
import { DatosBasicos } from './DatosBasicos.js'; // Mismo directorio
import { useMiembroFormLogic } from '../../hooks/useMiembroFormLogic.js'; // 2 niveles arriba
import { miembroCreateSchema } from '../../schemas/miembro.schema.js';
import type { Miembro } from '../../types/miembro.types.js';Imports entre recursos
typescript
// Categoria/components/AssignCategoriaModal.tsx
import { useMiembroList } from '../../Miembro/hooks/useMiembro.js';
import type { Miembro } from '../../Miembro/types/miembro.types.js';Imports desde shared
typescript
// Miembro/components/MiembroForm/DatosBasicos.tsx
import { SelectionModeToggle } from '../../../shared/components/SelectionModeToggle.js';
import type { SelectionMode } from '../../../shared/types/selectionMode.types.js';Imports desde core
typescript
// Miembro/components/MiembroForm/index.tsx
import { FormActions } from '../../../core/components/form/layout/FormActions.js';
import { useConfig } from '../../../core/context/ConfigContext.js';Carpeta shared/
¿Qué va en shared/?
✅ Incluir:
- Componentes usados por 2+ recursos diferentes
- Types compartidos entre recursos (ej:
SelectionMode) - Utilidades usadas por múltiples recursos
❌ No incluir:
- Código usado solo por un recurso (mantenerlo en el recurso)
- Código global del sistema (va en
core/)
Estructura de shared/
shared/
├── components/ # Componentes compartidos del módulo
│ ├── SelectionModeToggle.tsx
│ └── BulkActionsBar.tsx
│
├── types/ # Types compartidos
│ ├── selectionMode.types.ts
│ └── bulkAssignment.types.ts
│
├── schemas/ # Validaciones compartidas
│ └── selectionMode.schema.ts
│
└── utils/ # Utilidades compartidas
└── arrayHelpers.tsChecklist de Calidad
Al crear un nuevo recurso:
- [ ] Carpeta raíz con nombre PascalCase:
{Recurso}/ - [ ] Subcarpetas:
components/,hooks/,services/,schemas/,types/,views/ - [ ] Al menos un componente principal con
index.tsx - [ ] Al menos un hook
use{Recurso}.ts - [ ] Al menos un service
{recurso}.service.ts - [ ] Al menos un schema
{recurso}.schema.ts - [ ] Al menos un type
{recurso}.types.ts - [ ] View principal en
views/{Recurso}View.tsx
Al crear un componente complejo:
- [ ] Crear subcarpeta si tiene 3+ archivos relacionados
- [ ] Usar
index.tsxpara el componente principal - [ ] Eliminar prefijos redundantes en sub-componentes
- [ ] Crear
utils.tssi hay helpers específicos - [ ] Crear
types.tslocal si hay types solo de ese componente
Al organizar modales:
- [ ] Si son 3+ modales del mismo tipo, crear carpeta
{Tipo}Modals/ - [ ] Usar nombres cortos:
AddModal.tsx,EditModal.tsx,DeleteConfirmModal.tsx - [ ] Si es 1-2 modales, dejar en
components/directo
Ejemplos Reales
Recurso Simple (TipoRelacion)
TipoRelacion/
├── components/
│ └── TipoRelacionForm/
│ └── index.tsx
├── hooks/
│ ├── useTipoRelacion.ts
│ └── useTipoRelacionCrud.ts
├── services/
│ └── tipoRelacion.service.ts
├── schemas/
│ └── tipoRelacion.schema.ts
├── types/
│ └── tipoRelacion.types.ts
└── views/
└── TipoRelacionView.tsxRecurso Complejo (Miembro)
Miembro/
├── components/
│ ├── MiembroForm/
│ │ ├── index.tsx
│ │ ├── DatosBasicos.tsx
│ │ ├── DatosComerciales.tsx
│ │ ├── DatosMembresia.tsx
│ │ ├── AccionesAdicionales.tsx
│ │ └── utils.ts
│ ├── MiembroTable/
│ │ └── index.tsx
│ ├── AltaBajaModals/
│ │ ├── AltaMiembroModal.tsx
│ │ └── BajaMiembroModal.tsx
│ ├── DisciplinaModals/
│ │ ├── AddModal.tsx
│ │ ├── EditModal.tsx
│ │ ├── DeleteConfirmModal.tsx
│ │ └── ListModal.tsx
│ └── ProductoModals/
│ ├── AddModal.tsx
│ ├── EditModal.tsx
│ ├── DeleteConfirmModal.tsx
│ └── ListModal.tsx
├── hooks/
│ ├── useMiembro.ts
│ ├── useMiembroTableSSR.ts
│ ├── useMiembroFormLogic.ts
│ ├── useMiembroFormModals.ts
│ ├── useMiembroDisciplina.ts
│ └── useMiembroProducto.ts
├── services/
│ ├── miembro.service.ts
│ ├── miembroDisciplina.service.ts
│ └── miembroProducto.service.ts
├── schemas/
│ ├── miembro.schema.ts
│ ├── miembroDisciplina.schema.ts
│ └── miembroProducto.schema.ts
├── types/
│ ├── miembro.types.ts
│ ├── miembroDisciplina.types.ts
│ └── miembroProducto.types.ts
├── mappers/
│ └── miembro.mapper.ts
└── views/
├── MiembroView.tsx
└── MiembroFormView.tsxAnti-Patrones a Evitar
❌ Prefijos redundantes
typescript
// ❌ MAL
MiembroForm/
├── MiembroFormDatosBasicos.tsx
├── MiembroFormDatosComerciales.tsx
└── MiembroFormDatosMembresia.tsx
// ✅ BIEN
MiembroForm/
├── DatosBasicos.tsx
├── DatosComerciales.tsx
└── DatosMembresia.tsx❌ Carpetas innecesarias
typescript
// ❌ MAL (componente simple con 1 archivo)
DisciplinaForm/
└── index.tsx
// ✅ BIEN
DisciplinaForm.tsx❌ Mezclar concerns
typescript
// ❌ MAL
Miembro/
├── MiembroForm.tsx # Componente
├── useMiembro.ts # Hook
├── miembro.service.ts # Service
└── DisciplinaModal.tsx # ← De otro recurso!
// ✅ BIEN
Miembro/
├── components/
│ └── MiembroForm/
├── hooks/
│ └── useMiembro.ts
└── services/
└── miembro.service.ts
Disciplina/
├── components/
│ └── DisciplinaModal.tsx❌ shared/ como cajón de sastre
typescript
// ❌ MAL
shared/
├── MiembroHelpers.ts # ← Específico de Miembro, no compartido
├── SelectionMode.tsx # ✅ OK (usado por varios recursos)
└── CategoriaUtils.ts # ← Específico de Categoria
// ✅ BIEN
Miembro/
└── utils/
└── helpers.ts
shared/
└── components/
└── SelectionMode.tsx
Categoria/
└── utils/
└── utils.tsÚltima actualización: 2026-01-29 Relacionado con: Estructura de Módulos React