Todos los artículos

Cómo estructurar un proyecto de React que escale

La arquitectura que usan los equipos profesionales para organizar proyectos React grandes: estructura de carpetas, separación de capas y patrones que evitan el caos.

Cómo estructurar un proyecto de React que escale

Uno de los mayores problemas en proyectos React medianos y grandes no es el código en sí — es la organización. Cuando el proyecto crece, una estructura improvisada se convierte en una deuda técnica que ralentiza a todo el equipo. Esta guía muestra cómo estructurar un proyecto React desde el principio para que escale sin convertirse en un laberinto.

El error más común: estructura plana

La mayoría de los proyectos empiezan así:

src/
  components/
    Header.jsx
    Footer.jsx
    UserCard.jsx
    ProductList.jsx
    ProductCard.jsx
    CartItem.jsx
    Modal.jsx
    Button.jsx
    ... (50 componentes más)
  pages/
    Home.jsx
    Products.jsx
    Cart.jsx
  App.jsx

Funciona para proyectos pequeños. En proyectos medianos, encontrar qué toca qué se vuelve imposible.

La estructura que escala: Feature-First

La idea central es agrupar el código por dominio de negocio, no por tipo técnico:

src/
  features/
    auth/
      components/
        LoginForm.jsx
        RegisterForm.jsx
      hooks/
        useAuth.js
      services/
        authService.js
      store/
        authSlice.js
      index.js          ← API pública del feature
    products/
      components/
        ProductCard.jsx
        ProductList.jsx
        ProductFilters.jsx
      hooks/
        useProducts.js
        useProductSearch.js
      services/
        productService.js
      index.js
    cart/
      components/
        CartDrawer.jsx
        CartItem.jsx
        CartSummary.jsx
      hooks/
        useCart.js
      store/
        cartSlice.js
      index.js
  shared/
    components/
      Button/
        Button.jsx
        Button.module.css
        Button.test.jsx
        index.js
      Modal/
      Input/
    hooks/
      useDebounce.js
      useLocalStorage.js
      useMediaQuery.js
    utils/
      formatDate.js
      formatCurrency.js
      validators.js
    constants/
      routes.js
      apiEndpoints.js
  pages/
    HomePage.jsx
    ProductsPage.jsx
    CartPage.jsx
  layouts/
    MainLayout.jsx
    AuthLayout.jsx
  lib/
    apiClient.js      ← instancia configurada de axios/fetch
    queryClient.js    ← React Query config
  App.jsx
  main.jsx

Las reglas que hacen que esto funcione

Regla 1: Los features solo se importan desde su index.js

Cada feature expone una API pública a través de su index.js. El resto del app no importa desde dentro del feature:

// ✅ Correcto
import { ProductCard, useProducts } from '@/features/products';

// ❌ Incorrecto — viola el encapsulamiento
import ProductCard from '@/features/products/components/ProductCard';

Esto te permite reorganizar el interior de un feature sin romper nada fuera de él.

Regla 2: Los features no se importan entre sí

Si el feature cart necesita datos de products, no importa directamente desde features/products. En su lugar, usa el store global o define una interfaz compartida en shared/:

// ❌ Crea dependencias circulares difíciles de gestionar
import { useProducts } from '@/features/products';

// ✅ Usa el store o una capa compartida
import { selectProductById } from '@/store/selectors';

Regla 3: Componentes compartidos en shared/, no en features

Si dos features usan el mismo componente, ese componente pertenece a shared/components/. Los features solo tienen componentes que son exclusivamente suyos.

Separación de capas dentro de un feature

products/
  components/   ← Presentación pura: props in, JSX out
  hooks/        ← Lógica y estado
  services/     ← Llamadas a la API
  store/        ← Estado global (Redux/Zustand)

Ejemplo concreto: hook separado del componente

// hooks/useProducts.js — solo lógica
import { useQuery } from '@tanstack/react-query';
import { productService } from '../services/productService';

export function useProducts(filters) {
  return useQuery({
    queryKey: ['products', filters],
    queryFn: () => productService.getAll(filters),
    staleTime: 5 * 60 * 1000,
  });
}
// components/ProductList.jsx — solo presentación
import { useProducts } from '../hooks/useProducts';
import { ProductCard } from './ProductCard';
import { Skeleton } from '@/shared/components/Skeleton';

export function ProductList({ filters }) {
  const { data: products, isLoading, error } = useProducts(filters);

  if (isLoading) return <Skeleton count={6} />;
  if (error) return <p>Error al cargar productos.</p>;

  return (
    <div className="product-grid">
      {products.map(p => <ProductCard key={p.id} product={p} />)}
    </div>
  );
}

El componente no sabe nada de cómo se obtienen los datos. El hook no sabe nada de cómo se muestran.

Configurar alias de rutas

Con Vite, configura alias para evitar ../../../shared/components/Button:

// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
});
// jsconfig.json (para autocomplete en VS Code)
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  }
}

Cuándo aplicar esta estructura

No necesitas esto desde el día uno. Una estructura feature-first añade complejidad inicial que no se justifica para proyectos pequeños.

Empieza con la estructura plana si:

  • Eres el único desarrollador
  • El proyecto tiene menos de 20-30 componentes
  • Es un prototipo o MVP

Migra a feature-first cuando:

  • El equipo creció a 3+ desarrolladores
  • Tienes más de 5 secciones/dominios distintos en el app
  • El tiempo para encontrar archivos empieza a ser un problema

La buena noticia es que migrar gradualmente es posible: extrae un feature a la vez, empezando por el dominio más grande o más activo.

¿Necesitas ayuda con esto?

En Zerep construimos productos digitales, capacitamos equipos y ayudamos a negocios a crecer en internet.

Ver servicios Contáctanos

Zerep

Agencia de ingeniería de software. Construimos productos digitales, capacitamos equipos y ayudamos a negocios a crecer en internet.

TRABAJA CON NOSOTROS

Cotiza ahora, empieza hoy

Escríbenos y te respondemos en menos de 24 horas. Sin compromisos, sin letras chiquitas.

Ayudamos a tu marca a crecer en redes sociales y buscadores, con el uso de las mejores herramientas del mercado.

Google
Slack
GitHub
GitLab
Atlassian
Spotify
PayPal
Airbnb
Dropbox
Shopify