<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Khriztian Moreno</title>
    <description>The latest articles on Forem by Khriztian Moreno (@khriztianmoreno).</description>
    <link>https://forem.com/khriztianmoreno</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F192167%2Fe34249a8-fbd3-48ce-8afc-1418d0b944a7.jpeg</url>
      <title>Forem: Khriztian Moreno</title>
      <link>https://forem.com/khriztianmoreno</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/khriztianmoreno"/>
    <language>en</language>
    <item>
      <title>Tech Stack 2025</title>
      <dc:creator>Khriztian Moreno</dc:creator>
      <pubDate>Fri, 03 Jan 2025 21:57:30 +0000</pubDate>
      <link>https://forem.com/khriztianmoreno/tech-stack-2025-3684</link>
      <guid>https://forem.com/khriztianmoreno/tech-stack-2025-3684</guid>
      <description>&lt;p&gt;El ecosistema React es un paisaje dinámico de tecnologías en constante evolución. Este artículo profundiza en un potente stack tecnológico para construir aplicaciones full-stack en 2025, permitiéndote dar vida a tu propio producto (como un SaaS) o a su Producto Mínimo Viable (MVP).&lt;/p&gt;

&lt;p&gt;Como desarrollador web Fullstack experimentado, he pasado años perfeccionando mi enfoque. Las reevaluaciones anuales de los stack tecnológicos son cruciales para equilibrar las tendencias de vanguardia con la estabilidad y la mantenibilidad de los proyectos a largo plazo.&lt;/p&gt;

&lt;p&gt;Mi última experiencia laboral, que culminó en noviembre de 2024, me ha proporcionado valiosos comentarios. Aunque estoy satisfecho con el stack tecnológico inicial, la retrospectiva ofrece valiosas lecciones para futuros proyectos.&lt;/p&gt;

&lt;p&gt;Embarquémonos en este viaje de descubrimiento y exploremos las apasionantes posibilidades que aguardan en esta concisa pero potente selección.&lt;/p&gt;

&lt;h2&gt;
  
  
  React como framework full-stack
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Remix.js
&lt;/h3&gt;

&lt;p&gt;Remix.js es un framework web full-stack que prioriza la experiencia del desarrollador y aprovecha los fundamentos web para crear aplicaciones web rápidas, resilientes y amigables para el usuario.&lt;/p&gt;

&lt;h4&gt;
  
  
  Características Clave:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Carga y Obtención de Datos:&lt;/strong&gt; Remix simplifica la obtención de datos con cargadores y acciones integradas. Los loaders obtienen datos antes de renderizar una ruta, mientras que las acciones manejan envíos de formularios y otros efectos secundarios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enrutamiento Basado en el Sistema de Archivos:&lt;/strong&gt; Las rutas se definen como archivos dentro del sistema de archivos de tu proyecto, haciendo que la estructura de enrutamiento sea intuitiva y fácil de entender.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Renderizado del Lado del Servidor (SSR):&lt;/strong&gt; Remix sobresale en SSR, proporcionando un excelente SEO y tiempos de carga iniciales más rápidos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transmisión de Datos:&lt;/strong&gt; Remix puede transmitir datos al cliente, mejorando el rendimiento percibido y la experiencia del usuario.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manejo de Formularios:&lt;/strong&gt; El manejo de formularios integrado simplifica tareas comunes como la validación, el envío y el manejo de errores.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pruebas:&lt;/strong&gt; Remix fomenta las pruebas a varios niveles, incluyendo pruebas unitarias, de integración y de extremo a extremo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibilidad:&lt;/strong&gt; Remix se puede desplegar en varios entornos, incluyendo servidores Node.js y plataformas de computación en el borde como Cloudflare Workers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Beneficios de Usar Remix:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mejor Rendimiento:&lt;/strong&gt; SSR y la transmisión de datos contribuyen a tiempos de carga más rápidos y una experiencia de usuario más fluida.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mejor Experiencia del Desarrollador:&lt;/strong&gt; El enfoque de Remix en la experiencia del desarrollador lo hace agradable de usar, gracias a su enrutamiento intuitivo, mecanismos de obtención de datos y características integradas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibilidad y Escalabilidad:&lt;/strong&gt; Remix se puede desplegar en varios entornos, haciéndolo adaptable a diferentes necesidades de proyectos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comunidad y Ecosistema Sólidos:&lt;/strong&gt; Remix tiene una comunidad en crecimiento y un ecosistema de apoyo con varios recursos y herramientas disponibles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En esencia, Remix.js ofrece un enfoque moderno y eficiente para el desarrollo web, empoderando a los desarrolladores para construir aplicaciones de alta calidad, de alto rendimiento y centradas en el usuario.&lt;/p&gt;

&lt;h3&gt;
  
  
  Astro
&lt;/h3&gt;

&lt;p&gt;¿Considerando una landing page dedicada? ¡Astro brilla para esta tarea!&lt;/p&gt;

&lt;p&gt;Mientras que Remix.js sobresale en aplicaciones monolíticas que sirven tanto contenido estático como dinámico, Astro ofrece una alternativa convincente específicamente para crear landing pages excepcionales. Aquí está el porqué Astro podría ser la elección perfecta:&lt;/p&gt;

&lt;h4&gt;
  
  
  Características Clave:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rendimiento Ultra-Rápido:&lt;/strong&gt; Astro prioriza la velocidad, entregando landing pages rapidísimas que mantienen a los visitantes comprometidos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enrutamiento Intuitivo Basado en Archivos:&lt;/strong&gt; Similar a Remix, Astro aprovecha un sistema de enrutamiento basado en archivos, haciendo que sea fácil estructurar y gestionar el contenido de tu landing page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Desarrollo Basado en Componentes:&lt;/strong&gt; Construye componentes reutilizables para un proceso de desarrollo optimizado y un diseño consistente en toda tu landing page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integración con Múltiples Frameworks:&lt;/strong&gt; Astro se integra sin problemas con frameworks populares como React, Vue y Svelte, permitiéndote aprovechar tus habilidades y preferencias existentes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Soporte para Sistemas de Gestión de Contenidos (CMS) Headless:&lt;/strong&gt; Astro se lleva bien con varias soluciones CMS headless, permitiendo una gestión flexible del contenido de tu landing page.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Beneficios de Usar Astro para Páginas de Aterrizaje
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enfoque en la Experiencia del Desarrollador:&lt;/strong&gt; La sintaxis limpia de Astro y su estructura basada en archivos simplifican el desarrollo, permitiéndote concentrarte en crear una landing page impactante.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prototipado Rápido:&lt;/strong&gt; La velocidad de Astro lo hace ideal para el prototipado rápido y la iteración en el diseño de tu landing page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimización SEO:&lt;/strong&gt; Astro genera HTML limpio y bien estructurado, contribuyendo a una fuerte Optimización para Motores de Búsqueda (SEO) para tu landing page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tiempos de Construcción Reducidos:&lt;/strong&gt; Las construcciones incrementales de Astro minimizan los tiempos de construcción, permitiendo ciclos de desarrollo más rápidos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Al aprovechar las fortalezas de Astro, puedes crear una landing page de alto rendimiento y amigable para el desarrollador que capture leads y alimente el crecimiento de tu SaaS, todo mientras ahorras tiempo valioso para enfocarte en el desarrollo del producto principal dentro de tu aplicación Remix/Next.&lt;/p&gt;

&lt;h3&gt;
  
  
  Server Components
&lt;/h3&gt;

&lt;p&gt;Imagina que estás construyendo una casa. Los Componentes del Servidor son como los trabajadores de construcción que manejan las tareas pesadas y especializadas. En lugar de hacer todo dentro de tu casa (el navegador), estos componentes trabajan afuera, en el servidor.&lt;/p&gt;

&lt;h4&gt;
  
  
  ¿Qué hacen?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Obtener materiales:&lt;/strong&gt; Recuperan datos de una base de datos o API, como ir a buscar ladrillos para construir una pared.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hacer cálculos complejos:&lt;/strong&gt; Realizan operaciones matemáticas o lógicas complicadas, como calcular el área de una habitación.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proteger tu casa:&lt;/strong&gt; Manejan tareas de seguridad, como verificar si alguien tiene permiso para entrar.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ¿Por qué son útiles?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tu casa se construye más rápido:&lt;/strong&gt; Al hacer parte del trabajo en el servidor, tu sitio web carga más rápido para los visitantes.&lt;/li&gt;
&lt;li&gt;T*&lt;em&gt;u casa es más segura:&lt;/em&gt;* Los datos sensibles se manejan en un lugar más seguro, fuera del alcance de los intrusos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Puedes enfocarte en la decoración:&lt;/strong&gt; Los componentes del servidor manejan el trabajo pesado, para que puedas enfocarte en hacer que tu sitio web se vea bien y funcione bien.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Server Functions
&lt;/h3&gt;

&lt;p&gt;Piensa en tu casa teniendo un sistema de intercomunicación. Las Funciones del Servidor son como usar ese intercomunicador para pedirle a un trabajador afuera de la casa que haga algo.&lt;/p&gt;

&lt;h4&gt;
  
  
  ¿Cómo funcionan?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Tú (tu componente React) le dices al trabajador (la función del servidor) qué hacer, como "por favor trae más ladrillos".&lt;/li&gt;
&lt;li&gt;El trabajador hace la tarea y te da el resultado.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ¿Por qué son útiles?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Es muy fácil comunicarse:&lt;/strong&gt; No tienes que preocuparte por los detalles técnicos de enviar y recibir mensajes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Puedes hacer muchas cosas:&lt;/strong&gt; Puedes pedirle a la función del servidor que haga casi cualquier cosa que un componente del servidor pueda hacer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Server Actions
&lt;/h3&gt;

&lt;p&gt;Imagina que tienes una lista de comandos predefinidos para tu intercomunicador. Las Acciones del Servidor son como esos comandos.&lt;/p&gt;

&lt;h4&gt;
  
  
  ¿Qué son?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Son funciones del servidor diseñadas para realizar tareas específicas, como enviar un formulario o actualizar una base de datos.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ¿Por qué son útiles?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Son fáciles de usar:&lt;/strong&gt; Ya están configuradas para hacer algo específico, por lo que no tienes que escribir mucho código.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hay muchas bibliotecas que te ayudan:&lt;/strong&gt; Hay bibliotecas como next-safe-actions y zsa que te proporcionan acciones del servidor predefinidas para tareas comunes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Gestión de Estado en React
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Zustand
&lt;/h3&gt;

&lt;p&gt;Zustand es una biblioteca de gestión de estado ligera y flexible para aplicaciones React. Ofrece una API simple e intuitiva para gestionar el estado global y local, lo que la convierte en una excelente opción para proyectos de todos los tamaños.&lt;/p&gt;

&lt;h4&gt;
  
  
  Características Clave:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API Minimalista:&lt;/strong&gt; Zustand cuenta con una API concisa y fácil de aprender con un código boilerplate mínimo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orientado al Rendimiento:&lt;/strong&gt; Zustand está diseñado para un rendimiento óptimo, con actualizaciones de estado eficientes y una sobrecarga mínima.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible:&lt;/strong&gt; Ofrece un enfoque flexible y modular para la gestión de estado, permitiéndote crear y gestionar múltiples stores según sea necesario.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fácil de Aprender:&lt;/strong&gt; La API simple y la documentación clara hacen que Zustand sea fácil de aprender e integrar en tus proyectos React.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zustand&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})),&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStore&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;increment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStore&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;increment&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Count: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Recoil
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://recoiljs.org/" rel="noopener noreferrer"&gt;Recoil.js&lt;/a&gt; es una biblioteca de gestión de estado para aplicaciones React que proporciona un enfoque más granular y flexible para gestionar el estado compartido en comparación con métodos tradicionales como Context API. Ofrece un gráfico de flujo de datos único que te permite crear estructuras de estado complejas y derivar nuevo estado a partir de los existentes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Conceptos Clave:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Átomos:&lt;/strong&gt; Son las unidades fundamentales de estado en Recoil. Los átomos son independientes y pueden ser suscritos por múltiples componentes. Proporcionan una forma de almacenar y compartir valores simples.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Selectores:&lt;/strong&gt; Los selectores son funciones puras que derivan nuevo estado a partir de átomos existentes u otros selectores. Permiten crear estructuras de estado complejas y realizar cálculos sobre la marcha.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RecoilRoot:&lt;/strong&gt; Este componente es la raíz de tu aplicación Recoil. Proporciona el contexto para todos los átomos y selectores de Recoil.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Suscripciones:&lt;/strong&gt; Los componentes se suscriben a átomos o selectores para recibir actualizaciones cuando el estado cambia. Recoil utiliza mecanismos eficientes para asegurar que los componentes solo se vuelvan a renderizar cuando los datos de los que dependen realmente han cambiado.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Características Avanzadas:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Valores Asíncronos:&lt;/strong&gt; Recoil soporta valores asíncronos, permitiéndote obtener datos de APIs y gestionar estados de carga.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistencia:&lt;/strong&gt; Puedes persistir el estado de Recoil en el almacenamiento local u otros mecanismos de almacenamiento para restaurarlo en cargas de página posteriores.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Depuración con Viaje en el Tiempo:&lt;/strong&gt; Recoil proporciona herramientas para la depuración con viaje en el tiempo, permitiéndote inspeccionar y retroceder cambios de estado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hooks Personalizados:&lt;/strong&gt; Puedes crear hooks personalizados para encapsular lógica compleja de gestión de estado.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRecoilState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRecoilValue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;recoil&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Atom for user data (fetched asynchronously)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userDataAtom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;userData&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;effects_UNSTABLE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;setSelf&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Fetch user data from API and set it&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Selector to extract the user's name&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userNameSelector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;userName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userDataAtom&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;userData&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Guest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRecoilValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userNameSelector&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello, &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;userName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Estilos CSS en React
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Tailwind CSS
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Revolucionario para el Desarrollo Rápido&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aunque las opiniones sobre Tailwind CSS varían dentro de la comunidad de desarrolladores, creo firmemente que actualmente es la solución más efectiva para el desarrollo rápido de productos y el mantenimiento a largo plazo de CSS.&lt;/p&gt;

&lt;p&gt;Basado en mi propia experiencia y en los comentarios de muchos compañeros de trabajo, Tailwind ofrece varias ventajas clave:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prototipado Rápido:&lt;/strong&gt; El enfoque de utilidades primero de Tailwind permite a los desarrolladores construir y estilizar rápidamente elementos de la UI sin escribir clases CSS personalizadas. Esto acelera significativamente el proceso de prototipado e iteración.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Estilo Consistente:&lt;/strong&gt; Tailwind proporciona un conjunto predefinido de clases de utilidad, asegurando un estilo consistente en todo tu proyecto. Esto elimina la necesidad de reinventar constantemente la rueda y ayuda a mantener un sistema de diseño cohesivo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mejor Experiencia del Desarrollador:&lt;/strong&gt; La sintaxis intuitiva de Tailwind y las características de autocompletado en los editores de código modernos mejoran la experiencia del desarrollador, haciendo que escribir y mantener CSS sea más rápido y agradable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reducción del Tamaño del Archivo CSS:&lt;/strong&gt; Al aprovechar las clases de utilidad predefinidas, a menudo puedes reducir significativamente el tamaño total de tus archivos CSS, lo que lleva a tiempos de carga de página más rápidos y un mejor rendimiento.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comunidad y Ecosistema Sólidos:&lt;/strong&gt; Tailwind cuenta con una comunidad grande y activa, proporcionando acceso a documentación extensa, recursos útiles y una gran cantidad de plugins y extensiones construidos por la comunidad.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En mi experiencia, la curva de aprendizaje inicial de Tailwind es relativamente menor. La mayoría de los desarrolladores se vuelven competentes en una semana, y los beneficios a largo plazo en términos de velocidad de desarrollo y mantenibilidad superan con creces la inversión inicial.&lt;/p&gt;

&lt;p&gt;Te animo a probar Tailwind. Podrías sorprenderte de cuánto puede simplificar tu flujo de trabajo de CSS y aumentar tu productividad.&lt;/p&gt;

&lt;h2&gt;
  
  
  Obtención de datos en React
&lt;/h2&gt;

&lt;h3&gt;
  
  
  React/Tanstack Query
&lt;/h3&gt;

&lt;p&gt;Para la mayoría de las necesidades de obtención de datos, priorizo los &lt;strong&gt;Componentes del Servidor&lt;/strong&gt; debido a sus ventajas inherentes de rendimiento y mejora en la seguridad de los datos. Al manejar la carga de datos en el servidor, puedo minimizar la cantidad de JavaScript ejecutado en el navegador, lo que resulta en cargas iniciales de página más rápidas y una mejor experiencia de usuario.&lt;/p&gt;

&lt;p&gt;Sin embargo, para escenarios más complejos como el &lt;strong&gt;scroll infinito&lt;/strong&gt;, la &lt;strong&gt;paginación&lt;/strong&gt; o las &lt;strong&gt;actualizaciones de datos en tiempo real&lt;/strong&gt;, aprovecho el poder de &lt;strong&gt;React Query&lt;/strong&gt;. &lt;a href="https://tanstack.com/query/v3/" rel="noopener noreferrer"&gt;React Query&lt;/a&gt; proporciona una solución robusta y flexible para gestionar la obtención de datos, el almacenamiento en caché y las actualizaciones en el lado del cliente.&lt;/p&gt;

&lt;h4&gt;
  
  
  Ejemplo:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Componentes del Servidor:&lt;/strong&gt; Ideal para obtener datos iniciales para una página de producto, perfil de usuario o publicación de blog.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Query:&lt;/strong&gt; Excelente para implementar scroll infinito en un feed, gestionar datos paginados en una tabla o manejar actualizaciones en tiempo real para una aplicación de chat.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Al combinar estratégicamente Componentes del Servidor y React Query, puedo lograr un equilibrio óptimo entre rendimiento, mantenibilidad y experiencia del desarrollador en mis aplicaciones React.&lt;/p&gt;

&lt;h2&gt;
  
  
  Base de Datos &amp;amp; ORM
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prisma
&lt;/h3&gt;

&lt;p&gt;Mi Elección Preferida para Interacciones con la Base de Datos&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.prisma.io/" rel="noopener noreferrer"&gt;Prisma ORM&lt;/a&gt; sigue siendo mi elección preferida para interactuar con bases de datos en mis proyectos React. Aunque ORMs más nuevos como Drizzle están ganando tracción, Prisma ha demostrado ser una solución estable y confiable con una comunidad fuerte y documentación extensa.&lt;/p&gt;

&lt;h4&gt;
  
  
  Características Clave de Prisma:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Seguridad de Tipos:&lt;/strong&gt; Prisma genera tipos de TypeScript a partir de tu esquema de base de datos, asegurando la seguridad de tipos en toda tu aplicación y reduciendo el riesgo de errores en tiempo de ejecución.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findUnique&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Los tipos generados para &lt;code&gt;user&lt;/code&gt; y &lt;code&gt;posts&lt;/code&gt; proporcionan una guía clara y previenen estructuras de datos inesperadas.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Definición Declarativa del Esquema:&lt;/strong&gt; Define tu esquema de base de datos usando Prisma Schema Language, una sintaxis declarativa e intuitiva.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model User {
  id Int @id @default(autoincrement())
  name String
  email String @unique
  posts Post[]
}

model Post {
  id Int @id @default(autoincrement())
  title String
  content String
  author User @relation(fields: [authorId], references: [id])
  authorId Int
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Consulta Simplificada:&lt;/strong&gt; Prisma proporciona una API de creación de consultas fluida e intuitiva, lo que facilita la escritura de consultas complejas a la base de datos con un esfuerzo mínimo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migraciones:&lt;/strong&gt; Prisma Migrate simplifica los cambios en el esquema de la base de datos con un sistema de migración fácil de usar, permitiéndote evolucionar tu base de datos de manera segura con el tiempo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Beneficios de Usar Prisma
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Aumento de la Productividad:&lt;/strong&gt; Prisma mejora significativamente la productividad del desarrollador al automatizar tareas repetitivas, como la generación de consultas SQL y la gestión de cambios en el esquema de la base de datos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mejora de la Calidad del Código:&lt;/strong&gt; La seguridad de tipos, los tipos generados y el enfoque en las mejores prácticas contribuyen a una mayor calidad del código y a menos errores.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mantenibilidad Mejorada:&lt;/strong&gt; El enfoque declarativo de Prisma y las definiciones claras del esquema facilitan la comprensión y el mantenimiento de las interacciones con la base de datos a lo largo del tiempo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comunidad y Ecosistema Sólidos:&lt;/strong&gt; Prisma cuenta con una comunidad grande y activa, proporcionando acceso a documentación extensa, tutoriales y recursos de soporte.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aunque ORMs más nuevos como Drizzle ofrecen características prometedoras, la estabilidad de Prisma, su ecosistema maduro y su fuerte enfoque en la experiencia del desarrollador lo convierten en mi elección preferida para la mayoría de los proyectos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supabase
&lt;/h3&gt;

&lt;p&gt;Supabase es una alternativa de código abierto a Firebase que ofrece una suite completa de servicios backend, incluyendo una base de datos PostgreSQL en tiempo real, autenticación, almacenamiento y edge-functions. Proporciona a los desarrolladores una forma rápida y eficiente de construir aplicaciones web full-stack sin la molestia de gestionar la infraestructura.&lt;/p&gt;

&lt;h4&gt;
  
  
  Características Clave de Supabase:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL en Tiempo Real:&lt;/strong&gt; Supabase aprovecha PostgreSQL por sus capacidades robustas de base de datos, permitiéndote crear modelos de datos complejos y realizar consultas poderosas. Las características en tiempo real te permiten construir aplicaciones con actualizaciones en vivo, como aplicaciones de chat y paneles de control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Autenticación:&lt;/strong&gt; Supabase proporciona un sistema de autenticación flexible que soporta varios métodos como email/contraseña, inicios de sesión sociales y proveedores de autenticación personalizados. También ofrece características como autenticación sin contraseña y autenticación multifactor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Almacenamiento:&lt;/strong&gt; Supabase incluye un servicio de almacenamiento de archivos que te permite subir y gestionar archivos directamente desde tu aplicación. Puedes generar URLs públicas para los archivos y establecer permisos para controlar el acceso.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Funciones en el Borde:&lt;/strong&gt; Estas funciones serverless te permiten ejecutar código personalizado en el borde, más cerca de tus usuarios. Esto es útil para tareas como transformación de datos, renderizado del lado del servidor y lógica de autenticación personalizada.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API GraphQL:&lt;/strong&gt; Además de la API REST, Supabase también ofrece una API GraphQL, proporcionando una forma más flexible y expresiva de consultar tus datos.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ¿Por Qué Elegir Supabase?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Desarrollo Rápido:&lt;/strong&gt; Supabase acelera el desarrollo proporcionando servicios backend preconstruidos, permitiéndote enfocarte en construir el frontend de tu aplicación.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escalabilidad:&lt;/strong&gt; Supabase está construido sobre una infraestructura escalable, haciéndolo adecuado para aplicaciones de todos los tamaños.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Código Abierto:&lt;/strong&gt; Al ser de código abierto, Supabase ofrece transparencia, flexibilidad y una comunidad fuerte.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rentable:&lt;/strong&gt; Supabase ofrece un generoso nivel gratuito y planes de precios flexibles, haciéndolo asequible para proyectos pequeños y grandes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Cuándo Usar Supabase
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Aplicaciones en Tiempo Real:&lt;/strong&gt; Supabase es ideal para aplicaciones que requieren actualizaciones en tiempo real, como aplicaciones de chat, herramientas colaborativas y paneles de control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prototipado Rápido:&lt;/strong&gt; La facilidad de uso de Supabase lo convierte en una excelente opción para construir rápidamente prototipos y MVPs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aplicaciones Web Full-Stack:&lt;/strong&gt; Supabase puede ser utilizado como el backend para aplicaciones web tanto simples como complejas.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Manejo y Validación de Datos
&lt;/h2&gt;

&lt;h3&gt;
  
  
  TypeScript
&lt;/h3&gt;

&lt;p&gt;TypeScript es innegablemente el estándar de la industria para proyectos JavaScript. Su sistema de tipos estático, combinado con características modernas como interfaces y módulos, ofrece una serie de ventajas, como una mayor seguridad de tipos, una mejor detección de errores, una mayor productividad y una experiencia de desarrollo más agradable. La adopción de TypeScript por parte de la industria es un testimonio de su valor y eficacia.&lt;/p&gt;

&lt;h3&gt;
  
  
  Zod
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Una poderosa herramienta para la validación Type-Safe&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Zod ha emergido como una opción líder para la validación en proyectos React, particularmente cuando se combina con TypeScript. Al aprovechar el enfoque de tipo seguro de Zod, puede mejorar significativamente la robustez y la capacidad de mantenimiento de sus aplicaciones.&lt;/p&gt;

&lt;h4&gt;
  
  
  Características Clave de Zod
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Validación Segura por Tipos:&lt;/strong&gt; Zod aprovecha el sistema de tipos de TypeScript para definir y hacer cumplir esquemas de datos. Esto asegura que los datos recibidos por tu aplicación se ajusten a la estructura esperada, previniendo errores inesperados y mejorando la integridad de los datos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Esquemas Declarativos:&lt;/strong&gt; Zod te permite definir esquemas de datos de manera declarativa usando una sintaxis concisa y expresiva. Esto facilita la creación de reglas de validación complejas para tus datos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manejo de Errores:&lt;/strong&gt; Zod proporciona mensajes de error detallados e informativos, lo que facilita la identificación y corrección de problemas de validación. Estos mensajes de error pueden integrarse fácilmente en tu interfaz de usuario para proporcionar retroalimentación útil a los usuarios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensibilidad:&lt;/strong&gt; Zod ofrece una API flexible y extensible, permitiéndote crear reglas de validación personalizadas e integrarlas con otras partes de tu aplicación.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Beneficios de Usar Zod
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mejora de la Calidad del Código:&lt;/strong&gt; Al hacer cumplir tipos de datos y reglas de validación, Zod te ayuda a escribir código más robusto y confiable con menos errores inesperados.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mejora de la Experiencia del Desarrollador:&lt;/strong&gt; El enfoque seguro por tipos de Zod y sus mensajes de error informativos mejoran significativamente la experiencia del desarrollador al facilitar la escritura, depuración y mantenimiento de tu código.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mejora de la Experiencia del Usuario:&lt;/strong&gt; Al proporcionar mensajes de error claros y útiles a los usuarios, Zod ayuda a mejorar la experiencia general del usuario de tu aplicación.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reducción de Costos de Mantenimiento:&lt;/strong&gt; Al detectar problemas de validación de datos desde el principio, Zod puede ayudar a reducir los costos de mantenimiento a largo plazo asociados con tu aplicación.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Mi Enfoque
&lt;/h4&gt;

&lt;p&gt;Aunque Zod ofrece potentes capacidades de validación del lado del cliente, prefiero usarlo principalmente para la validación del lado del servidor, particularmente dentro de las Acciones del Servidor. Este enfoque mantiene los formularios del lado del cliente ligeros y evita la complejidad introducida por muchas bibliotecas de formularios de terceros. Al confiar en la validación nativa de HTML para verificaciones básicas, puedo mantener una arquitectura de componentes de formularios ágil y eficiente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pruebas y herramientas
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Mock Service Worker (MSW)
&lt;/h3&gt;

&lt;p&gt;Una herramienta que ha mejorado drásticamente mi flujo de trabajo es Mock Service Worker (&lt;a href="https://mswjs.io/" rel="noopener noreferrer"&gt;MSW&lt;/a&gt;). Si aún no la usas, déjame mostrarte por qué merece tu atención.&lt;/p&gt;

&lt;p&gt;Mock Service Worker es una potente librería JavaScript para API mocking. Intercepta peticiones a nivel de red usando Service Workers, permitiéndote simular APIs directamente en el navegador o en tiempo de ejecución Node.js. Esto lo hace perfecto para pruebas, depuración e incluso desarrollo sin depender de un backend.&lt;/p&gt;

&lt;h4&gt;
  
  
  Por qué me encanta usar MSW
&lt;/h4&gt;

&lt;p&gt;Para mí, MSW resuelve muchos problemas que otras librerías de mocking no pueden:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mocking Realista:&lt;/strong&gt; MSW intercepta solicitudes a nivel de red, por lo que el comportamiento simulado es casi indistinguible de un servidor real. Es como tener un emulador de backend en tu bolsillo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pruebas de Cliente y Servidor:&lt;/strong&gt; Ya sea que estés probando una aplicación React o un servicio Node.js, MSW funciona perfectamente en ambos entornos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reducción de Dependencias:&lt;/strong&gt; No necesitas servidores de prueba adicionales ni configuraciones de mocking complejas. MSW lo mantiene limpio y simple.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibilidad:&lt;/strong&gt; Puedes simular APIs REST, GraphQL e incluso WebSocket. Si tu aplicación puede hacer la solicitud, MSW puede simularla.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mejor Depuración:&lt;/strong&gt; Con registros claros y herramientas de depuración, sabes exactamente qué solicitudes están siendo simuladas y cómo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  MSW vs. Herramientas Mocking Tradicionales
&lt;/h3&gt;

&lt;p&gt;En mi experiencia, MSW destaca sobre herramientas como los interceptores Axios o los mocks personalizados:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Escalabilidad:&lt;/strong&gt; Con MSW, tus mocks viven fuera de la lógica de tu aplicación, haciéndolos reutilizables y mantenibles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aislamiento:&lt;/strong&gt; A diferencia de los interceptores, MSW no interfiere con el código de tu aplicación. Esto significa que no hay código desordenado de desmontaje después de las pruebas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comportamiento Similar al Navegador:&lt;/strong&gt; Al usar Service Workers, MSW imita el comportamiento a nivel del navegador, asegurando que tus pruebas sean lo más cercanas posible a las condiciones del mundo real.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Por Qué Deberías Probar MSW
&lt;/h4&gt;

&lt;p&gt;Las APIs son la columna vertebral de las aplicaciones modernas, y probarlas no tiene por qué ser doloroso. MSW proporciona una forma realista, flexible y amigable para el desarrollador de simular APIs sin complejidad innecesaria.&lt;/p&gt;

&lt;p&gt;Ya sea que estés desarrollando, depurando o probando, MSW es un cambio de juego. Es la herramienta que no sabía que necesitaba, pero de la que ahora no puedo prescindir.&lt;/p&gt;

&lt;p&gt;Si estás buscando elevar tu proceso de desarrollo en 2025, prueba MSW. Tu equipo te lo agradecerá y tu código brillará.&lt;/p&gt;

&lt;h3&gt;
  
  
  Playwright
&lt;/h3&gt;

&lt;p&gt;Cuando se trata de pruebas web modernas en 2025, Playwright se ha convertido en una de mis herramientas de referencia. No es sólo una biblioteca de pruebas; se siente como una herramienta de poder para los desarrolladores front-end que quieren precisión, velocidad y versatilidad.&lt;/p&gt;

&lt;p&gt;Playwright es una biblioteca Node.js para la automatización del navegador. Creada por Microsoft, permite escribir pruebas de extremo a extremo para aplicaciones web en los principales navegadores (Chromium, Firefox, WebKit) con una API coherente. Es como tener una navaja suiza para las pruebas de navegador que es elegante, potente y fácil de usar para los desarrolladores.&lt;/p&gt;

&lt;h4&gt;
  
  
  Por qué destaca Playwright
&lt;/h4&gt;

&lt;p&gt;Desde mi experiencia, Playwright destaca en:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Soporte Multi-Navegador:&lt;/strong&gt; A diferencia de Cypress, que solo soporta navegadores basados en Chromium de forma predeterminada, Playwright te permite probar en Chromium, Firefox y WebKit. Esto lo hace indispensable para asegurar que tu aplicación funcione en diferentes entornos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pruebas en Paralelo:&lt;/strong&gt; La paralelización integrada de Playwright es un cambio de juego. Las pruebas se ejecutan más rápido, lo que mantiene la tubería de CI fluida y a los desarrolladores productivos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modos Headless y Headed:&lt;/strong&gt; Ya sea que estés depurando o ejecutando pruebas en CI, Playwright se adapta sin problemas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aislamiento de Contextos:&lt;/strong&gt; Con Playwright, puedes crear contextos de navegador aislados que imitan diferentes usuarios. Esto es una salvación para aplicaciones con flujos de autenticación complejos o escenarios multi-tenant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pruebas de API:&lt;/strong&gt; Playwright no se detiene en la UI. Puedes hacer llamadas API directamente dentro de tus scripts de prueba, asegurando que tu front-end y back-end funcionen armoniosamente.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Veamos algo de código&lt;/p&gt;

&lt;p&gt;He aquí un ejemplo rápido de cómo escribir una prueba Playwright en TypeScript. Esta prueba comprueba una página de inicio de sesión:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@playwright/test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Login Page Tests&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should log in successfully with valid credentials&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Fill out the login form&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#username&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;testuser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;securepassword&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button[type="submit"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Assert redirection to the dashboard&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/dashboard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toHaveText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Welcome, testuser!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should show an error for invalid credentials&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Fill out the form with invalid data&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#username&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wronguser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wrongpassword&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button[type="submit"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Assert error message is displayed&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.error-message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toHaveText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid credentials&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Las pruebas ya no son opcionales en 2025. Los usuarios esperan experiencias impecables, y la automatización es la forma de ofrecerlas. Playwright combina potencia con funciones fáciles de usar para los desarrolladores, lo que la convierte en una herramienta imprescindible.&lt;/p&gt;

&lt;p&gt;Si aún no la ha explorado, ahora es el momento. Su yo del futuro se lo agradecerá cuando sus pruebas se ejecuten más rápido, sus errores disminuyan y sus usuarios estén contentos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Despliegue y alojamiento
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Cloudflare (Dominio &amp;amp; CDN)
&lt;/h3&gt;

&lt;p&gt;Cloudflare sigue siendo una piedra angular del desarrollo web moderno. Para mí, no es sólo un servicio, es una parte integral de la creación de aplicaciones rápidas, seguras y escalables. Tanto si eres un desarrollador independiente como si formas parte de un gran equipo, Cloudflare tiene herramientas que elevarán tu pila.&lt;/p&gt;

&lt;h4&gt;
  
  
  ¿Qué es Cloudflare?
&lt;/h4&gt;

&lt;p&gt;Cloudflare es un conjunto completo de herramientas de rendimiento y seguridad web. Comenzó como una red de distribución de contenidos (CDN), pero hoy en día es mucho más. Con Cloudflare, puedes optimizar el rendimiento de tu sitio web, protegerlo de ataques maliciosos e incluso crear aplicaciones sin servidor utilizando su potente plataforma de computación edge.&lt;/p&gt;

&lt;h4&gt;
  
  
  Por qué confío en Cloudflare
&lt;/h4&gt;

&lt;p&gt;Estas son las razones más destacadas por las que Cloudflare es una parte esencial de mi stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Velocidad en Todas Partes:&lt;/strong&gt; Con su CDN global, Cloudflare asegura que los activos estáticos de tu aplicación se entreguen a la velocidad del rayo, sin importar dónde estén tus usuarios. Su caché es una salvación para aplicaciones con activos pesados o audiencias globales.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seguridad Inigualable:&lt;/strong&gt; El Firewall de Aplicaciones Web (WAF) y la protección contra DDoS de Cloudflare me han ahorrado innumerables dolores de cabeza. Es como tener un equipo de seguridad en piloto automático.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Computación Serverless en el Borde:&lt;/strong&gt; Usar Cloudflare Workers ha sido un cambio de juego. Me permite ejecutar funciones ligeras en el borde, reduciendo la latencia y descargando trabajo de los servidores tradicionales.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Facilidad de Uso:&lt;/strong&gt; Configurar Cloudflare toma minutos, pero los beneficios son inmensos. Su panel intuitivo y herramientas amigables para desarrolladores hacen que sea fácil integrarlo con cualquier stack.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rentable:&lt;/strong&gt; Por el valor que proporciona, el precio de Cloudflare es inmejorable. Incluso su nivel gratuito está lleno de características que pueden ayudarte a empezar sin preocuparte por los costos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Crear aplicaciones modernas significa ofrecer experiencias rápidas, seguras y fiables. Cloudflare te permite conseguir todo esto sin complicar en exceso tu stack. Desde su imbatible CDN hasta su innovadora plataforma Edge Computing, es una herramienta que recomendaría a cualquier desarrollador que quiera preparar sus aplicaciones para el futuro en 2025.&lt;/p&gt;

&lt;p&gt;Si aún no ha explorado Cloudflare, ahora es el momento perfecto. Sus usuarios notarán la diferencia, y usted también.&lt;/p&gt;

&lt;h2&gt;
  
  
  Otras Utilidades:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  React Email &amp;amp; Resend
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Una potente combinación para la entrega de correo electrónico&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;React Email y Resend ofrecen una solución convincente para crear y entregar correos electrónicos de alta calidad dentro de sus aplicaciones React.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://react.email/" rel="noopener noreferrer"&gt;React Email&lt;/a&gt;:&lt;/strong&gt; Esta biblioteca te permite crear plantillas de correo electrónico visualmente atractivas y responsivas directamente dentro de tus componentes React. Aprovechando conceptos familiares de React como componentes, estado y props, puedes crear diseños de correo electrónico dinámicos y fáciles de mantener.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://resend.com/" rel="noopener noreferrer"&gt;Resend&lt;/a&gt;:&lt;/strong&gt; Esta robusta API de correo electrónico proporciona una forma confiable y eficiente de enviar correos electrónicos transaccionales, como correos de bienvenida, restablecimientos de contraseña y confirmaciones de pedidos. Resend ofrece características como alta entregabilidad, análisis robustos e integración fácil con tu infraestructura existente.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Beneficios Clave
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mejor Experiencia del Desarrollador:&lt;/strong&gt; React Email mejora la experiencia del desarrollador al permitirte crear plantillas de correo electrónico utilizando patrones familiares de React, lo que lleva a una mayor productividad y mantenibilidad.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Branding Consistente:&lt;/strong&gt; Al usar componentes React para tus plantillas de correo electrónico, puedes asegurar un branding y estilo consistentes en toda tu aplicación, incluidos los correos electrónicos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mejor Entregabilidad:&lt;/strong&gt; La infraestructura robusta de Resend y su enfoque en la entregabilidad ayudan a asegurar que tus correos electrónicos lleguen a los destinatarios previstos de manera confiable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integración Fácil:&lt;/strong&gt; Resend ofrece una API sencilla y SDKs para una fácil integración con tu aplicación React.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/EmailTemplates/WelcomeEmail.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;P&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;H1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@react-email/components&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;WelcomeEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Welcome to Our App!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;H1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello, &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;H1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;P&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Welcome to our app! We're excited to have you join us.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;P&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... more email content ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/pages/api/sendWelcomeEmail.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Resend&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Resend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RESEND_API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;resend&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;no-reply@yourdomain.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;recipient@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Welcome to Our App!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;renderToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;WelcomeEmail&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Failed to send email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este ejemplo muestra cómo utilizar React Email para crear una plantilla de correo electrónico de bienvenida sencilla y, a continuación, utilizar la API Resend para enviarla.&lt;/p&gt;

&lt;p&gt;Al combinar la potencia de React Email y Resend, puede agilizar sus flujos de trabajo de correo electrónico, mejorar la calidad de sus comunicaciones por correo electrónico y mejorar la experiencia general del usuario.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stripe
&lt;/h3&gt;

&lt;p&gt;Stripe es una pasarela de pago robusta y ampliamente utilizada que ofrece un conjunto completo de funciones para aceptar pagos en línea.&lt;/p&gt;

&lt;h4&gt;
  
  
  Retos potenciales
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complejidad:&lt;/strong&gt; Aunque es potente, el amplio conjunto de características de Stripe puede resultar abrumador, especialmente para proyectos más pequeños o aquellos con requisitos de pago más simples.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API en Evolución:&lt;/strong&gt; Stripe introduce continuamente nuevas características y actualiza su API, lo que ocasionalmente puede requerir ajustes en tu integración.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loadStripe&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@stripe/stripe-js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stripePromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;loadStripe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YOUR_STRIPE_PUBLIC_KEY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;CheckoutForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stripePromise&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirectToCheckout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;lineItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;price_1234567890abc123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// Handle error (e.g., display an error message to the user)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... form fields ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Processing...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Pay Now&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;CheckoutForm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Esencialmente, esta es la pila tecnológica que yo elegiría hoy para un nuevo proyecto React full-stack. Esta es solo una combinación posible, y la mejor pila tecnológica para tu proyecto dependerá en última instancia de tus requisitos y prioridades específicos. Te animo a explorar estas tecnologías y experimentar con diferentes combinaciones para encontrar lo que mejor funciona para ti.&lt;/p&gt;

&lt;p&gt;¡Espero que esto haya sido útil y/o te haya enseñado algo nuevo!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rdbt84oh93va3vi70m5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rdbt84oh93va3vi70m5.png" alt="Profile" width="148" height="91"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;a class="mentioned-user" href="https://dev.to/khriztianmoreno"&gt;@khriztianmoreno&lt;/a&gt; 🚀
&lt;/h4&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>programmers</category>
    </item>
    <item>
      <title>Un senior destaca por su forma de pensar, no de codear</title>
      <dc:creator>Khriztian Moreno</dc:creator>
      <pubDate>Tue, 10 Dec 2024 20:23:42 +0000</pubDate>
      <link>https://forem.com/khriztianmoreno/un-senior-destaca-por-su-forma-de-pensar-no-de-codear-51h0</link>
      <guid>https://forem.com/khriztianmoreno/un-senior-destaca-por-su-forma-de-pensar-no-de-codear-51h0</guid>
      <description>&lt;p&gt;&lt;strong&gt;El análisis de edge cases: una clave para evaluar a desarrolladores senior&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;El mundo de la programación está en constante cambio, pero muchas empresas siguen usando métodos de evaluación obsoletos para medir las habilidades de los desarrolladores senior. Si bien las pruebas teóricas son útiles para medir conocimientos básicos, no reflejan con precisión la capacidad de un senior para resolver problemas complejos del mundo real.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.khriztianmoreno.dev%2Fposts%2Fedge-cases.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.khriztianmoreno.dev%2Fposts%2Fedge-cases.webp" alt="The analysis of edge cases" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Por qué las pruebas técnicas tradicionales no son suficientes?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Las pruebas basadas solo en conceptos teóricos no logran capturar el verdadero valor de un desarrollador senior. La experiencia de un senior se mide en su capacidad para anticipar problemas, diseñar soluciones escalables y optimizar sistemas. Un buen desarrollador senior no solo domina el código, sino que también sabe cómo manejar excepciones, gestionar la complejidad y pensar de manera crítica ante escenarios inciertos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;El enfoque práctico: análisis de edge cases&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Un ejercicio clave para evaluar a un desarrollador senior es presentarle un escenario realista y pedirle que identifique y resuelva los edge cases. Tomemos como ejemplo el desarrollo de una página con búsqueda y paginación. En una entrevista técnica, un senior experimentado debería ser capaz de pensar en escenarios extremos que podrían romper la funcionalidad, tales como:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CONTINUA LEYENDO EL POST EN&lt;/strong&gt; &lt;a href="https://blog.khriztianmoreno.dev/es/posts/a-senior-stands-out-for-his-thinking" rel="noopener noreferrer"&gt;MI BLOG&lt;/a&gt;&lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>programming</category>
    </item>
    <item>
      <title>Desbloquea tu creatividad con Google Gemini y JavaScript: Guía práctica</title>
      <dc:creator>Khriztian Moreno</dc:creator>
      <pubDate>Fri, 15 Mar 2024 16:50:56 +0000</pubDate>
      <link>https://forem.com/khriztianmoreno/desbloquea-tu-creatividad-con-google-gemini-y-javascript-guia-practica-hel</link>
      <guid>https://forem.com/khriztianmoreno/desbloquea-tu-creatividad-con-google-gemini-y-javascript-guia-practica-hel</guid>
      <description>&lt;p&gt;Hola! Hoy les traigo una nueva herramienta que potenciará tu creatividad a otro nivel: &lt;strong&gt;Google Gemini&lt;/strong&gt;. Esta API de inteligencia artificial te permite generar texto de alta calidad en español, desde simples frases hasta historias completas, con solo unas pocas líneas de código.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es Google Gemini?
&lt;/h2&gt;

&lt;p&gt;Google Gemini es un modelo de lenguaje de última generación desarrollado por Google AI. Se ha entrenado con un conjunto de datos masivo de texto y código, lo que le permite comprender y generar lenguaje natural con una precisión impresionante.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué podemos hacer con Google Gemini y JavaScript?
&lt;/h2&gt;

&lt;p&gt;Las posibilidades son infinitas. Aquí te presento algunos ejemplos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Generar contenido creativo&lt;/strong&gt;: Escribe poemas, historias, guiones, artículos de blog, o cualquier tipo de contenido textual que puedas imaginar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Traducir idiomas&lt;/strong&gt;: Traduce textos de un idioma a otro de forma rápida y precisa.
Responder preguntas: Obtén respuestas a tus preguntas de forma informativa y completa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crear chatbots&lt;/strong&gt;: Desarrolla chatbots conversacionales que interactúen con los usuarios de forma natural.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatizar tareas&lt;/strong&gt;: Automatiza la generación de informes, correos electrónicos, y otras tareas que requieren procesamiento de lenguaje natural.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Cómo empezar?
&lt;/h2&gt;

&lt;p&gt;Para empezar a usar Google Gemini con JavaScript, solo necesitas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Una cuenta de Google Cloud Platform&lt;/strong&gt;: &lt;a href="https://cloud.google.com/"&gt;https://cloud.google.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Habilitar la API de Google Gemini&lt;/strong&gt;: &lt;a href="https://ai.google.dev/"&gt;https://ai.google.dev/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Ejemplo práctico:
&lt;/h2&gt;

&lt;p&gt;En este ejemplo, vamos a generar un poema usando Google Gemini y JavaScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GoogleGenerativeAI&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@google/generative-ai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Access your API key as an environment variable (see "Set up your API key" above)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;genAI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GoogleGenerativeAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// For embeddings, use the embedding-001 model&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;genAI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getGenerativeModel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;embedding-001&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Escribe un poema sobre la naturaleza&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;embedContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;embedding&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;embedding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para la generación de texto usamos el método &lt;code&gt;getGenerativeModel&lt;/code&gt; del objeto genAI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ejemplo de poema generado:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;La tierra verde, el cielo azul,
el sol brilla con luz de cristal.
Las flores florecen en el jardín,
los pájaros cantan con dulce trino.

El viento susurra entre las hojas,
las abejas zumban entre las flores.
La naturaleza es un regalo divino,
un lugar de paz y armonía.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusión:
&lt;/h2&gt;

&lt;p&gt;Google Gemini y JavaScript son una combinación poderosa que te permite desbloquear tu creatividad y desarrollar aplicaciones increíbles. Con esta guía práctica, ya estás listo para empezar a explorar las posibilidades infinitas de esta tecnología.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recursos adicionales:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Documentación de Google Gemini&lt;/strong&gt;: &lt;a href="https://ai.google.dev/docs"&gt;https://ai.google.dev/docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tutoriales de Google Gemini&lt;/strong&gt;: &lt;a href="https://m.youtube.com/watch?v=TXvbT8ORI50"&gt;https://m.youtube.com/watch?v=TXvbT8ORI50&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ejemplos de código de Google Gemini&lt;/strong&gt;: &lt;a href="https://m.youtube.com/watch?v=jTdouaDuUOA"&gt;https://m.youtube.com/watch?v=jTdouaDuUOA&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;¡Anímate a experimentar con Google Gemini y JavaScript!&lt;/strong&gt; Comparte tus creaciones en los comentarios y déjame saber qué te parece esta herramienta.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>ai</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Cómo mockear una solicitud HTTP con Jest 💻</title>
      <dc:creator>Khriztian Moreno</dc:creator>
      <pubDate>Fri, 23 Feb 2024 13:20:52 +0000</pubDate>
      <link>https://forem.com/khriztianmoreno/como-mockear-una-solicitud-http-con-jest-4e16</link>
      <guid>https://forem.com/khriztianmoreno/como-mockear-una-solicitud-http-con-jest-4e16</guid>
      <description>&lt;p&gt;Hoy quería mostrarles cómo escribir correctamente una prueba.&lt;/p&gt;

&lt;p&gt;Pero cualquiera puede encontrar cómo ejecutar una prueba sencilla. Y aquí, buscamos ayudarle a encontrar respuestas que no encontrará en ningún otro lugar.&lt;/p&gt;

&lt;p&gt;Entonces pensé que llevaríamos las cosas un paso más allá.&lt;/p&gt;

&lt;p&gt;Ejecutemos una prueba más compleja, en la que tendrás que simular 1 o 2 partes de la función que estás probando.&lt;/p&gt;

&lt;p&gt;[En caso de que seas nuevo aquí: mock es como usar un doble en una película. Es una forma de reemplazar una parte complicada de tu código (como llamar a una API) con algo más simple que pretende ser real, para que pueda probar el resto de tu código fácilmente].&lt;/p&gt;

&lt;p&gt;MI testing framework elegido es Jest, porque hace que todo sea mucho más fácil:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Configuración cero:&lt;/strong&gt; una de las principales ventajas de Jest es su configuración sin configuración. Está diseñado para funcionar desde el primer momento con una configuración mínima, lo que lo hace muy atractivo para proyectos que desean implementar pruebas de manera rápida y eficiente.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prueba de instantáneas:&lt;/strong&gt; Jest introdujo el concepto de Snapshot Testing, que es particularmente útil para probar componentes de la interfaz de usuario. Toma una instantánea de la salida renderizada de un componente y garantiza que no cambie inesperadamente en pruebas futuras.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mocking y Spies Integrados:&lt;/strong&gt; Jest viene con soporte integrado para funciones, módulos y temporizadores simulados, lo que facilita la prueba de componentes o funciones de forma aislada sin preocuparse por sus dependencias.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compatibilidad con pruebas asincrónicas:&lt;/strong&gt; Jest admite pruebas asincrónicas listas para usar, lo cual es esencial para las pruebas en aplicaciones JavaScript modernas que a menudo dependen de operaciones asincrónicas como llamadas API o consultas de bases de datos.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fau3m8kw0rtsrclm6s8fo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fau3m8kw0rtsrclm6s8fo.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De todos modos, entremos en las pruebas:&lt;/p&gt;

&lt;h3&gt;
  
  
  Paso 1: configurar tu proyecto
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Cree un nuevo directorio de proyecto y navegue hasta él&lt;/li&gt;
&lt;li&gt;Inicialice un nuevo proyecto npm: &lt;code&gt;npm init -y&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Instale Jest: &lt;code&gt;npm install --save-dev jest&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Instale axios para realizar solicitudes HTTP: &lt;code&gt;npm install axios&lt;/code&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Estos son los requisitos básicos. Nada nuevo o sofisticado aquí. Vamonos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Paso 2: escribir una función con una llamada API
&lt;/h3&gt;

&lt;p&gt;Ahora, digamos que inicia sesión en algún tipo de aplicación. StackOverflow, por ejemplo. Lo más probable es que en la parte superior derecha veas información sobre tu perfil. Tal vez su nombre completo y nombre de usuario, por ejemplo.&lt;/p&gt;

&lt;p&gt;Para obtenerlos, normalmente tenemos que realizar una llamada a la API para obtenerlos. Entonces, veamos cómo haríamos eso.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cree un archivo llamado &lt;code&gt;user.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Dentro de &lt;code&gt;user.js&lt;/code&gt;, escriba una función que realice una llamada API. Por ejemplo, usar axios para recuperar datos del usuario:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// user.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://api.example.com/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Paso 3: crear el archivo de prueba
&lt;/h3&gt;

&lt;p&gt;Bien, ahora que tenemos una función que nos trae el usuario según la identificación que solicitamos, veamos cómo podemos probarla.&lt;/p&gt;

&lt;p&gt;Recuerde, queremos algo que funcione siempre y para todos los desarrolladores.&lt;/p&gt;

&lt;p&gt;Lo que significa que no queremos depender de si el servidor se está ejecutando o no (ya que esto no es lo que estamos probando).&lt;/p&gt;

&lt;p&gt;Y no queremos depender de los usuarios que tenemos en la base de datos.&lt;/p&gt;

&lt;p&gt;Porque en mi base de datos, el ID1 podría pertenecer a mi usuario administrador, mientras que en su base de datos, el ID1 podría pertenecer a SU usuario administrador.&lt;/p&gt;

&lt;p&gt;Esto significa que la misma función nos daría resultados diferentes. Lo que haría que la prueba fallara, aunque la función funcione correctamente.&lt;/p&gt;

&lt;p&gt;Siga leyendo para ver cómo abordamos este problema mediante los mocks.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cree un archivo llamado &lt;code&gt;user.test.js&lt;/code&gt; en el mismo directorio.&lt;/li&gt;
&lt;li&gt;Dentro de este archivo, importe la función que desea probar:
```js
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;import axios from 'axios';&lt;br&gt;
jest.mock('axios');&lt;/p&gt;

&lt;p&gt;import { getUser } from './user';&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;3. Escriba su caso de prueba, simule la llamada y recupere datos simulados. 
```js


test('should fetch user data', async () =&amp;gt; {
  // Mock data to be returned by the Axios request
  const mockUserData = { id: '1', name: 'John Doe' };
  axios.get.mockResolvedValue({ data: mockUserData });

  // Call the function
  const result = await getUser('1');

  // Assert that the Axios get method was called correctly
  expect(axios.get).toHaveBeenCalledWith('https://api.example.com/users/1');

  // Assert that the function returned the correct data
  expect(result).toEqual(mockUserData);
});


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Paso 4: ejecutar la prueba
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Agregue un script de prueba a su &lt;code&gt;package.json&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jest"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Ejecute sus pruebas con &lt;code&gt;npm test&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Paso 5: revise los resultados
&lt;/h4&gt;

&lt;p&gt;Jest mostrará el resultado de su prueba en la terminal. La prueba debería pasar, lo que indica que &lt;code&gt;getUser&lt;/code&gt; está devolviendo los datos simulados como se esperaba.&lt;/p&gt;

&lt;p&gt;Felicitaciones, ahora tienes una prueba funcional con Jest y Mocking.&lt;/p&gt;

&lt;p&gt;¡Espero que esto haya sido útil y/o te haya hecho aprender algo nuevo!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rdbt84oh93va3vi70m5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rdbt84oh93va3vi70m5.png" alt="Profile"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;a class="mentioned-user" href="https://dev.to/khriztianmoreno"&gt;@khriztianmoreno&lt;/a&gt;
&lt;/h4&gt;

</description>
      <category>javascript</category>
      <category>testing</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>¿Estás cometiendo ESTOS errores de pruebas y mocking unitarios?</title>
      <dc:creator>Khriztian Moreno</dc:creator>
      <pubDate>Fri, 16 Feb 2024 18:26:04 +0000</pubDate>
      <link>https://forem.com/khriztianmoreno/estas-cometiendo-estos-errores-de-pruebas-y-mocking-unitarios-16bb</link>
      <guid>https://forem.com/khriztianmoreno/estas-cometiendo-estos-errores-de-pruebas-y-mocking-unitarios-16bb</guid>
      <description>&lt;p&gt;Las pruebas son difíciles.&lt;/p&gt;

&lt;p&gt;Y no importa si eres un tester experimentado o principiante...&lt;/p&gt;

&lt;p&gt;Si ha realizado un esfuerzo significativo para probar una aplicación...&lt;/p&gt;

&lt;p&gt;Es probable que hayas cometido algunos de estos errores de prueba y mocking en el pasado.&lt;/p&gt;

&lt;p&gt;Desde casos de prueba repletos de código duplicado y enormes hooks de ciclo de vida, hasta casos de mocking convenientemente incorrectos y casos extremos que faltan y furtivos, hay muchos culpables comunes.&lt;/p&gt;

&lt;p&gt;He seguido algunos de los casos más populares y los enumero a continuación. Continúe y cuente cuántos de ellos ha hecho en el pasado.&lt;/p&gt;

&lt;p&gt;Con suerte, será una buena ronda.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Por qué la gente comete errores en las pruebas en primer lugar?
&lt;/h2&gt;

&lt;p&gt;Si bien las pruebas automatizadas son una de las partes más importantes del proceso de desarrollo...&lt;/p&gt;

&lt;p&gt;Y las pruebas unitarias nos ahorran innumerables horas de pruebas manuales e innumerables errores que quedan atrapados en los conjuntos de pruebas...&lt;/p&gt;

&lt;p&gt;Muchas empresas no utilizan pruebas unitarias o no ejecutan suficientes pruebas.&lt;/p&gt;

&lt;p&gt;¿Sabía que la cobertura de prueba promedio de un proyecto es de ~40%, mientras que la recomendada es del 80%?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0b6f88et53xwtximyb9y.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0b6f88et53xwtximyb9y.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esto significa que mucha gente no está acostumbrada a ejecutar pruebas (especialmente casos de prueba complejos) y cuando no estás acostumbrado a hacer algo, eres más propenso a cometer un error.&lt;/p&gt;

&lt;p&gt;Entonces, sin más preámbulos, veamos algunos de los errores de prueba más comunes que veo&lt;/p&gt;

&lt;h3&gt;
  
  
  Código duplicado
&lt;/h3&gt;

&lt;p&gt;Las tres reglas más importantes del desarrollo de software son también las tres reglas más importantes de las pruebas.&lt;/p&gt;

&lt;p&gt;¿Cuáles son estas reglas?&lt;br&gt;
&lt;strong&gt;Reutilizar. Reutilizar. Reutilizar&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Un problema común que veo es repetir la misma serie de comandos en cada prueba en lugar de moverlos a un enlace de ciclo de vida como &lt;code&gt;beforeEach&lt;/code&gt; o &lt;code&gt;afterEach&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Esto podría deberse a que el desarrollador estaba creando un prototipo o a que el proyecto era pequeño y el cambio insignificante. Estos casos son buenos y aceptables.&lt;/p&gt;

&lt;p&gt;Pero unos cuantos casos de prueba más tarde, el problema de la duplicación de código se vuelve cada vez más evidente.&lt;/p&gt;

&lt;p&gt;Y aunque esto es más bien un error de un desarrollador junior, el siguiente es similar pero mucho más astuto.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sobrecargar los hooks del ciclo de vida
&lt;/h3&gt;

&lt;p&gt;En la otra cara de la misma moneda, a veces estamos demasiado ansiosos por refactorizar nuestros casos de prueba y ponemos tantas cosas en los hooks del ciclo de vida sin pensarlo dos veces que no vemos el problema que nos estamos creando.&lt;/p&gt;

&lt;p&gt;A veces, los hooks del ciclo de vida crecen demasiado.&lt;/p&gt;

&lt;p&gt;Y cuando esto sucede...&lt;/p&gt;

&lt;p&gt;...y necesitas desplazarte hacia arriba y hacia abajo para ir desde el hook al caso de prueba y viceversa...&lt;/p&gt;

&lt;p&gt;Esto es un problema y a menudo se lo denomina "fatiga de desplazamiento".&lt;/p&gt;

&lt;p&gt;Recuerdo haber sido culpable de esto en el pasado.&lt;/p&gt;

&lt;p&gt;Un patrón/práctica común para mantener el archivo legible cuando tenemos hooks de ciclo de vida inflados es extraer el código de configuración común en pequeñas funciones de fábrica.&lt;/p&gt;

&lt;p&gt;Entonces, imaginemos que tenemos algunas (docenas de) casos de prueba que se ven así:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authController&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;signup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;given user object, returns response with 201 status&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Arrange&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// several lines of user setup code&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dbUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// several lines of user setup code&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nf"&gt;mockingoose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toReturn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;findOne&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;mockingoose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toReturn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;save&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
                &lt;span class="c1"&gt;// several lines of constructing the request&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// several lines of constructing the response&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="c1"&gt;// Act&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;signup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mockResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;// Assert&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;given user object with email of an existing user, returns 400 status - 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Arrange&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// several lines of user setup code&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dbUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// several lines of user setup code&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
                &lt;span class="c1"&gt;// several lines of constructing the request&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// several lines of constructing the response&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nf"&gt;mockingoose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toReturn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;findOne&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// Act&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;signup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mockResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="c1"&gt;// Assert&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockJson&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockJson&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fail&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Email taken.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Podemos extraer la información de configuración repetida en sus propias funciones llamadas &lt;code&gt;createUserObject&lt;/code&gt;, &lt;code&gt;createDbUserObject&lt;/code&gt; y &lt;code&gt;createMocks&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Y luego las pruebas quedarían así:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;given user object, returns response with 201 status&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createUserObject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dbUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createDbUserObject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;mockRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mockResponse&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createMocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;mockingoose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toReturn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;findOne&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;mockingoose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toReturn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;save&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;signup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mockResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Al extraer esos fragmentos de código en sus propias funciones de fábrica separadas, podemos evitar la fatiga del desplazamiento, mantener los enlaces del ciclo de vida ágiles y facilitar la navegación por el archivo y encontrar lo que estamos buscando.&lt;/p&gt;

&lt;h3&gt;
  
  
  No priorizar los tipos de pruebas que ejecutas
&lt;/h3&gt;

&lt;p&gt;Esto tiene más que ver con bases de código grandes o enormes donde hay literalmente cientos o incluso miles de casos de prueba ejecutándose cada vez que una nueva serie de commits quiere fusionarse en la base de código.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubhoe5naa6ww40jkao00.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubhoe5naa6ww40jkao00.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En tales casos, ejecutar todos los conjuntos de pruebas puede llevar literalmente horas y es posible que no siempre tenga el tiempo o los recursos para hacerlo.&lt;/p&gt;

&lt;p&gt;Cuando el tiempo o los recursos están limitados, es importante elegir estratégicamente el tipo de prueba a priorizar. Generalmente, las pruebas de integración brindan mejores garantías de confiabilidad debido a su alcance más amplio. Por lo tanto, cuando se tiene que elegir entre los dos, suele ser una buena idea elegir las pruebas de integración en lugar de las pruebas unitarias.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmk7shvlsw5c3x09ebmbo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmk7shvlsw5c3x09ebmbo.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Usar lógica en tus casos de prueba
&lt;/h3&gt;

&lt;p&gt;Queremos evitar la lógica en nuestros casos de prueba siempre que sea posible.&lt;/p&gt;

&lt;p&gt;Los casos de prueba solo deben tener una validación simple y evitar cosas como bloques &lt;code&gt;try-catch&lt;/code&gt; o condicionales &lt;code&gt;if-else&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Esto mantiene tus pruebas limpias y enfocadas solo en el flujo esperado porque hace que las pruebas sean más fáciles de entender de un vistazo.&lt;/p&gt;

&lt;p&gt;La única excepción es cuando estás escribiendo funciones auxiliares o de fábrica que configuran escenarios para pruebas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Utilizar validaciones vagas en lugar de afirmaciones estrictas
&lt;/h3&gt;

&lt;p&gt;Esto suele ser una señal de que es posible que necesites refactorizar el fragmento de código que estás probando o que necesites hacer un ajuste menor en tus mocks.&lt;/p&gt;

&lt;p&gt;Por ejemplo, en lugar de comprobar si el valor es mayor que 1, deberías ser más específico y afirmar que el valor es 2.&lt;/p&gt;

&lt;p&gt;O, si está verificando los datos de un objeto Usuario, debe afirmar que cada dato es exactamente como lo espera, en lugar de simplemente verificar una coincidencia de ID.&lt;/p&gt;

&lt;p&gt;Los controles sueltos pueden enmascarar casos extremos que podrían fallar en el futuro.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementación incorrecta del Mock Behavior
&lt;/h3&gt;

&lt;p&gt;Este es difícil de encontrar y es por eso que puedes encontrar un ejemplo en cada código base.&lt;/p&gt;

&lt;p&gt;Es uno de los problemas de prueba más astutos pero comunes y es difícil notarlo a primera vista.&lt;/p&gt;

&lt;p&gt;Puede suceder cuando el comportamiento del mock está demasiado simplificado o cuando no refleja con precisión los casos extremos y las condiciones de error.&lt;/p&gt;

&lt;p&gt;Como resultado, las pruebas pueden pasar, pero no proporcionarán una indicación confiable de cómo funcionará el sistema bajo diversas condiciones, lo que resulta en errores futuros y problemas inesperados, y casos de prueba con comportamiento simulado que terminan haciendo más daño que bien.&lt;/p&gt;

&lt;p&gt;Espero este post te ayude a indetificar esas practicas que deberiamos evitar al momento de hacer pruebas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rdbt84oh93va3vi70m5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rdbt84oh93va3vi70m5.png" alt="Profile"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a class="mentioned-user" href="https://dev.to/khriztianmoreno"&gt;@khriztianmoreno&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Hasta la próxima.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>testing</category>
    </item>
    <item>
      <title>Por qué es tan difícil pasar el estado entre los componentes del cliente y del servidor</title>
      <dc:creator>Khriztian Moreno</dc:creator>
      <pubDate>Tue, 09 Jan 2024 13:58:25 +0000</pubDate>
      <link>https://forem.com/khriztianmoreno/por-que-es-tan-dificil-pasar-el-estado-entre-los-componentes-del-cliente-y-del-servidor-4d8b</link>
      <guid>https://forem.com/khriztianmoreno/por-que-es-tan-dificil-pasar-el-estado-entre-los-componentes-del-cliente-y-del-servidor-4d8b</guid>
      <description>&lt;p&gt;La forma en que representamos los componentes del servidor es diferente. &lt;/p&gt;

&lt;p&gt;Nada parecido a lo que estamos acostumbrados hasta ahora. &lt;/p&gt;

&lt;p&gt;Y debido a que es tan diferente, también cambia dónde manejamos el estado, cómo lo manejamos y cómo logramos dormir por la noche sabiendo que todas estas son cosas importantes que deberíamos saber desde el año pasado, pero la mayoría de nosotros somos completamente inconscientes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Su-W8Vlu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t68b4i20k9yxdd8b07xu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Su-W8Vlu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t68b4i20k9yxdd8b07xu.jpg" alt="Image description" width="554" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De hecho, los componentes del servidor impactan 3 de las partes más importantes del desarrollo web:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Experiencia del usuario&lt;/li&gt;
&lt;li&gt;La forma en que nosotros, los desarrolladores, escribimos código y diseñamos nuestras aplicaciones.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No es algo que podamos ignorar o tomar a la ligera.&lt;/p&gt;

&lt;p&gt;Como puedes ver, he estado pensando mucho en ello y probablemente tú también lo hayas estado pensando. Todo desarrollador que valore su teclado está pensando en ello.&lt;/p&gt;

&lt;p&gt;Y está esta pregunta específica... Es como una pregunta del tipo “la gallina y el huevo”, principalmente porque ambas son preguntas que se hacen mucho.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Cómo diablos manejo el estado en los componentes del servidor si no tengo acceso al estado en primer lugar?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Antes de darte la respuesta, déjame explicarte el problema que nos ocupa. Considere lo que sucede cuando un componente del servidor solicita una nueva renderización.&lt;/p&gt;

&lt;p&gt;A diferencia de los componentes del cliente donde el estado se conserva entre renderizaciones, los componentes del servidor no pueden darse ese lujo. Como un juego pícaro, siempre empiezan desde cero.&lt;/p&gt;

&lt;p&gt;No existe ningún código o mecanismo inherente que pueda hacer que un componente del servidor recuerde el estado. El backend tiene todas esas bases de datos y patrones de diseño y todas esas funciones complejas y ¿para qué? Ni siquiera puede manejar el estado.&lt;/p&gt;

&lt;p&gt;¿Asi que que hacemos? ¿Utilizamos simplemente componentes de servidor en componentes completamente estáticos que no necesitan ningún estado? Si bien esta es una posible respuesta, también es un enfoque que limita la efectividad y el ajuste de los componentes del servidor en las aplicaciones web modernas. Entonces, lo estamos descartando.&lt;/p&gt;

&lt;p&gt;Porque todo lo que dije anteriormente tiene un inconveniente.&lt;/p&gt;

&lt;p&gt;Si bien es posible que el backend no maneje el estado del cliente como lo hace el cliente, sí maneja el estado de la aplicación. Entonces, en cierto modo, podemos manejar el estado en el servidor. Simplemente no de la forma en que lo piensas. Y, en realidad, no es una única manera.&lt;/p&gt;

&lt;p&gt;Y, en realidad, no es una única manera.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hay TRES formas de manejar el estado en el servidor.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cuál elegimos depende de lo que mejor se adapte a nuestras necesidades y situación actual. Y estas 3 formas son: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prop drilling desde el servidor a los componentes&lt;/li&gt;
&lt;li&gt;cookies&lt;/li&gt;
&lt;li&gt;state hydration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ahora, otra pregunta del millón. ¿Por qué no podemos simplemente manejar todos los estados en el cliente?&lt;/p&gt;

&lt;p&gt;Esto se debe a que los componentes del servidor abogan por una separación de preocupaciones. Lo que en términos más simples significa que cada parte de la aplicación debe ocuparse de sus propios asuntos. Al desacoplar el estado del renderizado, no solo mejoramos el rendimiento, sino que también obtenemos más control sobre la experiencia del usuario. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NXhSWTf8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/khriztianmoreno/image/upload/c_scale%2Cw_148/v1591324337/KM-brand/stickers/sticker-3_2x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NXhSWTf8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/khriztianmoreno/image/upload/c_scale%2Cw_148/v1591324337/KM-brand/stickers/sticker-3_2x.png" alt="Profile" width="148" height="91"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a class="mentioned-user" href="https://dev.to/khriztianmoreno"&gt;@khriztianmoreno&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Hasta la próxima.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>¿Seguirás utilizando componentes del lado del cliente en 2024?</title>
      <dc:creator>Khriztian Moreno</dc:creator>
      <pubDate>Fri, 05 Jan 2024 12:15:03 +0000</pubDate>
      <link>https://forem.com/khriztianmoreno/seguiras-utilizando-componentes-del-lado-del-cliente-en-2024-ogc</link>
      <guid>https://forem.com/khriztianmoreno/seguiras-utilizando-componentes-del-lado-del-cliente-en-2024-ogc</guid>
      <description>&lt;p&gt;Me encantan los componentes del servidor. Pero no son para todas las ocasiones. De hecho, usarlos en todas y cada una de las oportunidades que tengas es más como ablandar un bistec con el mismo martillo que usaste para clavar un alfiler.&lt;/p&gt;

&lt;p&gt;Dicho esto, también hay algunos casos en los que los componentes del servidor encajan como Cenicienta y su zapato.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dashboards &amp;amp; Reports
&lt;/h2&gt;

&lt;p&gt;En el caso de los paneles y los informes, se maximiza el rendimiento al procesar y representar todos los datos en el servidor y, al mismo tiempo, permitir que el cliente haga lo que se suponía que debía hacer en primer lugar.&lt;/p&gt;

&lt;p&gt;Si solo usamos componentes del cliente, le estamos descargando más tareas y haciendo que desempeñe más tareas de las que potencialmente puede manejar.&lt;/p&gt;

&lt;p&gt;Si procesó y representó los datos en el cliente, pasaría mucho tiempo esperando con un feo spinner burlándose de usted debido a todos los pasos adicionales que el cliente tiene que seguir para lograr el mismo resultado.&lt;/p&gt;

&lt;p&gt;Primero, necesitaría obtener los datos de su endpoint, que a su vez tendría que obtener datos de la base de datos, que a su vez tendría que obtener datos de sus registros.&lt;/p&gt;

&lt;p&gt;No sólo eso, sino que también hay que esperar pacientemente a que los datos lleguen al cliente, aunque llegue tarde.&lt;/p&gt;

&lt;p&gt;Y sólo una vez que llegan, el cliente puede comenzar a procesarlos y mostrárselos al usuario.&lt;/p&gt;

&lt;p&gt;Por eso, en este caso, es mejor tener los componentes bloqueados y renderizados directamente en el servidor.&lt;/p&gt;

&lt;p&gt;Y luego, el cliente puede obtener todos los widgets que su corazón electrónico desea, todos transmitidos en paralelo, lo que es una forma mucho más rápida y sencilla de realizar negocios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blog Posts
&lt;/h2&gt;

&lt;p&gt;Las publicaciones de blog son algunos de los contenidos más estáticos que puedes encontrar. Después de todo, se trata principalmente de un montón de palabras, en orden, con alguna imagen, gif o meme ocasional aquí y allá. &lt;/p&gt;

&lt;p&gt;Con los componentes del servidor, estás renderizando previamente el contenido en el servidor, que es el mejor de los casos en términos de SEO porque se entrega rápido y completo.&lt;/p&gt;

&lt;p&gt;Este caso de uso anterior es lo que tiende a desequilibrar a los desarrolladores y confundirlos. Porque las publicaciones de blogs son lo primero en lo que también piensan cuando se trata de SSR. Entonces, si piensan en SSR y componentes de servidor cuando piensan en publicaciones de blog, es natural pensar que ambos son lo mismo o que pueden usarse indistintamente.&lt;/p&gt;

&lt;p&gt;Lo cual es total y absolutamente incorrecto y es un pecado digno de arder en el infierno por la eternidad, según mi &lt;a href="https://dev.to/khriztianmoreno/server-components-vs-server-side-rendering-4ghe"&gt;blog post anterior&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Pero al mismo tiempo tiene sentido desde el punto de vista de los resultados. Porque aunque sus enfoques son muy diferentes en la práctica, los resultados son bastante similares.&lt;/p&gt;

&lt;h2&gt;
  
  
  Server-Side Data Fetching
&lt;/h2&gt;

&lt;p&gt;La obtención de datos del lado del servidor es una excelente manera de darle a su código un impulso de seguridad en caso de que, de lo contrario, revele lógica o claves API que se supone deben permanecer ocultas o si está paranoico con respecto a cada pieza de información que posee.&lt;/p&gt;

&lt;p&gt;Puede utilizar este tipo de obtención de datos para acceder no sólo a su base de datos sino también a cualquier otra API que desee. Todo ello siendo astuto.&lt;/p&gt;

&lt;p&gt;Sin embargo, hay casos en los que los componentes del servidor &lt;strong&gt;NO&lt;/strong&gt; son ideales y, de hecho, deben evitarse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requisitos de alta interactividad
&lt;/h2&gt;

&lt;p&gt;Esta es una redacción elegante para cualquier cosa a la que le haces algo y le devuelves algo. Algo así como gelatina, pero no tanto.&lt;/p&gt;

&lt;p&gt;Algo potencialmente más familiar y más acorde con el desarrollo web en sí son elementos como formularios y botones.&lt;/p&gt;

&lt;p&gt;Estos componentes a menudo tienen que reaccionar de alguna manera a sus acciones, pueden tener su propio estado y comunicarse con otros componentes en el lado del cliente, lo que los convierte en el eslabón más débil cuando se trata de componentes de servidor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stateful Components
&lt;/h2&gt;

&lt;p&gt;Si lo tomas lo más literalmente posible y usas la definición que hemos estado usando hasta ahora, no hay manera de manejar el estado en un componente del servidor.&lt;/p&gt;

&lt;p&gt;Pero si entrecierras los ojos, inclinas la cabeza un poco hacia un lado, desenfocas un poco y respiras profundamente, podrás ver que esto es sólo una verdad a medias.&lt;/p&gt;

&lt;p&gt;En otro momento aprenderemos cuáles son los matices, pero por ahora digamos que los componentes del servidor NO tienen acceso al estado. Después de todo, no tienen acceso a hooks relacionados con el estado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Los componentes del servidor son una herramienta poderosa para escenarios específicos en el desarrollo web. Utilícelos para mejorar el rendimiento y la seguridad de tareas con uso intensivo de datos. Pero recuerde, es posible que no se adapten a todas las situaciones, especialmente para elementos interactivos o con estado.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NXhSWTf8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/khriztianmoreno/image/upload/c_scale%2Cw_148/v1591324337/KM-brand/stickers/sticker-3_2x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NXhSWTf8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/khriztianmoreno/image/upload/c_scale%2Cw_148/v1591324337/KM-brand/stickers/sticker-3_2x.png" alt="Profile" width="148" height="91"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a class="mentioned-user" href="https://dev.to/khriztianmoreno"&gt;@khriztianmoreno&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Hasta la próxima.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Server Components Vs. Server-side Rendering</title>
      <dc:creator>Khriztian Moreno</dc:creator>
      <pubDate>Thu, 04 Jan 2024 14:02:56 +0000</pubDate>
      <link>https://forem.com/khriztianmoreno/server-components-vs-server-side-rendering-4ghe</link>
      <guid>https://forem.com/khriztianmoreno/server-components-vs-server-side-rendering-4ghe</guid>
      <description>&lt;p&gt;¿Sabías que los componentes del servidor y el renderizado del lado del servidor son dos cosas completamente diferentes?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---z0_1VPY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gikft6v2xsd073a1il47.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---z0_1VPY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gikft6v2xsd073a1il47.jpg" alt="Image description" width="589" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Y si bien van de la mano en muchos casos, hay igualmente muchos ejemplos en los que puedes y debes usar solo uno de ellos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MkM-Yw0Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/smpzsmnjj5ckq2g17z85.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MkM-Yw0Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/smpzsmnjj5ckq2g17z85.jpg" alt="Image description" width="606" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora bien, para ser justos, dada la documentación en línea que la mayoría de los desarrolladores encuentran sobre los componentes del servidor y el renderizado del lado del servidor, el hecho de que asuman que estas dos cosas son iguales no es exactamente una sorpresa. &lt;/p&gt;

&lt;p&gt;(Esto también les da la excusa perfecta para evitar los componentes del servidor por completo, en lugar de enfrentar el hecho de que esto es algo que ya deberían saber usar bastante bien y que eventualmente tendrán que aprender de todos modos)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IPFz11r6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/chw6m0iyg2ky9cy1xyvx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IPFz11r6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/chw6m0iyg2ky9cy1xyvx.jpg" alt="Image description" width="572" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dicho esto, los componentes del servidor tienen muchas ventajas sobre el renderizado del lado del servidor, especialmente cuando se trata de crear aplicaciones más grandes y complejas.&lt;/p&gt;

&lt;p&gt;Hablemos un poco más de las diferencias entre ambos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Server-Side Rendering
&lt;/h2&gt;

&lt;p&gt;La representación del lado del servidor representa la página en el servidor. Pero, obviamente, eso no es realmente útil, así que profundicemos un poco más.&lt;/p&gt;

&lt;p&gt;La representación del lado del servidor representa la página en el servidor en el &lt;strong&gt;momento de la solicitud&lt;/strong&gt;, lo que significa que &lt;strong&gt;cada vez que un cliente realiza una solicitud al servidor&lt;/strong&gt;, como cuando un nuevo visitante llega a su página, &lt;strong&gt;el servidor vuelve a representar la misma página&lt;/strong&gt; y la envía a el cliente.&lt;/p&gt;

&lt;p&gt;Y si bien esto es excelente para SEO, ya que incluso las &lt;strong&gt;páginas más dinámicas aparecen como estáticas a los ojos de los robots que las indexan y las usan para búsquedas&lt;/strong&gt;, la representación del lado del servidor tiene muchos pasos entre el cliente que realiza la solicitud al servidor y La página finalmente se carga frente a ti.&lt;/p&gt;

&lt;p&gt;Primero, cuando la solicitud llega al servidor, el servidor representa estáticamente la página y la envía de regreso al cliente, donde el usuario obtiene una versión de su página que está desprovista de toda interactividad.&lt;/p&gt;

&lt;p&gt;Pero eso no es lo único que el servidor envía al cliente. Junto con el HTML de la página estática, el servidor envía sus condolencias junto con un gran paquete de código React que el cliente deberá ejecutar para que la página vuelva a ser dinámica.&lt;/p&gt;

&lt;p&gt;Pero ¿qué pasa cuando el 90% de nuestra página es estática?&lt;/p&gt;

&lt;p&gt;Podrías pensar que la respuesta correcta es “prácticamente nada” y no estarías exactamente equivocado, pero al igual que en la clase de Cálculo, pierdes puntos porque esta no es la respuesta que estaba buscando.&lt;/p&gt;

&lt;p&gt;En realidad, todavía se envía una gran cantidad de JavaScript al cliente y debe ejecutarse sin cambiar mucho en la página misma.&lt;/p&gt;

&lt;p&gt;Esto es una pérdida de tiempo y datos y es una de las principales razones por las que se crearon los componentes del servidor.&lt;/p&gt;

&lt;p&gt;(Lo que también significa que si está utilizando SSR como alternativa a los componentes del servidor, ha tenido un gran problema y es hora de cambiar su forma de actuar antes de que lo arrojen a una cárcel de "rendimiento lento").&lt;/p&gt;

&lt;h2&gt;
  
  
  Server Components
&lt;/h2&gt;

&lt;p&gt;Los componentes del servidor, como SSR, se representan en el servidor, pero tienen la capacidad única de incluir lógica del lado del servidor sin enviar ningún JavaScript adicional al cliente, ya que los componentes del servidor se ejecutan en el servidor.&lt;/p&gt;

&lt;p&gt;Esto significa que mientras en SSR el código JavaScript se ejecuta en el cliente, en Server Components, el código se ejecuta directamente en el servidor. Y el cliente solo recibe la salida del código a través de la carga útil del servidor, como un bebé al que le mastican la comida.&lt;/p&gt;

&lt;p&gt;Entonces, en pocas palabras, la diferencia entre componentes de servidor y renderizado del lado del servidor tiene que ver con cuándo y cómo se ejecuta el código. En el caso de los componentes del servidor, no es necesario enviar ni manejar código adicional en el lado del cliente porque ya lo ejecutamos en el servidor.&lt;/p&gt;

&lt;p&gt;El único código necesario es si está uniendo los componentes del servidor y del cliente y el cliente tiene que unir los dos.&lt;/p&gt;

&lt;p&gt;El gran beneficio de los componentes de servidor es que ofrecen un mayor rendimiento porque necesitan menos JavaScript del lado del cliente y descargan todo el procesamiento y la recuperación de datos al servidor mientras el cliente puede relajarse y beber Aperol Spritz hasta que llegue el HTML renderizado.&lt;/p&gt;

&lt;p&gt;En ese momento, el cliente simplemente se lo muestra al usuario final y se lleva todo el crédito por el arduo trabajo realizado por el servidor.&lt;/p&gt;

&lt;p&gt;Y si bien esto puede parecer un poco complejo en este momento, todo se aclarará a medida que aprenda más sobre los componentes del servidor. Lo cual es algo que realmente no se puede evitar, ya que se están volviendo cada vez más populares en casos de uso como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tener muchos cálculos pesados ​​que necesitan mucho procesamiento&lt;/li&gt;
&lt;li&gt;Acceso API privado (para mantener el secreto… secret) &lt;/li&gt;
&lt;li&gt;Cuando la mayor parte del lado del cliente ya es estático y sería un desperdicio enviar más JavaScript al cliente&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Si bien los componentes de servidor pueden parecer desalentadores en este momento, en su mayoría son algo nuevo y extraño. Una vez que los conozcas mejor y aprendas algunos de los conceptos básicos, te darás cuenta de que no son tan complejos como parecen.&lt;/p&gt;

&lt;p&gt;La curva de aprendizaje no es tan pronunciada como podría pensar y solo porque tengan "sever" en el nombre, no significa que tengan que ser algo extraño y críptico de lo que los desarrolladores frontend debamos mantenernos alejados. De hecho, son bastante similares a los componentes del cliente e incluso más livianos ya que carecen de elementos como enlaces de estado, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NXhSWTf8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/khriztianmoreno/image/upload/c_scale%2Cw_148/v1591324337/KM-brand/stickers/sticker-3_2x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NXhSWTf8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/khriztianmoreno/image/upload/c_scale%2Cw_148/v1591324337/KM-brand/stickers/sticker-3_2x.png" alt="Profile" width="148" height="91"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a class="mentioned-user" href="https://dev.to/khriztianmoreno"&gt;@khriztianmoreno&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Hasta la próxima.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>react</category>
      <category>programming</category>
    </item>
    <item>
      <title>Predicciones 🧞‍♀️💻 2024</title>
      <dc:creator>Khriztian Moreno</dc:creator>
      <pubDate>Wed, 03 Jan 2024 15:28:21 +0000</pubDate>
      <link>https://forem.com/khriztianmoreno/predicciones-2024-fil</link>
      <guid>https://forem.com/khriztianmoreno/predicciones-2024-fil</guid>
      <description>&lt;p&gt;Algunos puntos que deberías prestar atención para este año 2024 que seguro tendrán un alto impacto en el ecosistema tecnológico.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bun logra su objetivo de convertirse en el runtime predeterminado para frontend:&lt;/strong&gt; Todavía tienen algunos obstáculos que superar, pero si logran proporcionar un reemplazo directo para Node que mejore instantáneamente el rendimiento de su aplicación 10 veces, será una opción obvia para la mayoría de los desarrolladores. El lanzamiento v1.0 de septiembre pasado fue un paso importante hacia la compatibilidad y la estabilidad general de Windows, y la apuesta es a que Bun comience a convertirse en la opción predeterminada este año.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;La IA reemplazará las herramientas no-code/low-code:&lt;/strong&gt; Resulta que la IA es mucho mejor y más rápida a la hora de crear paneles de análisis de marketing. Herramientas como &lt;a href="https://www.basedash.com/"&gt;Basedash&lt;/a&gt; y &lt;a href="https://archie.8base.com/"&gt;8base&lt;/a&gt; ya utilizan IA para crear un conjunto completo de requerimientos, herramientas internas personalizadas, y surgirán otras para reemplazar a los builders de arrastrar y soltar para crear sitios que no dependan en gran medida de la lógica empresarial.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Netlify es adquirida por GoDaddy:&lt;/strong&gt; Con múltiples rondas de despidos, 2023 claramente no fue el mejor año para Netlify. Pero a veces la mejor manera de recuperarse es buscarse un nuevo &lt;del&gt;sugar daddy&lt;/del&gt;, GoDaddy. Después de retirar la marca Media Temple hace unos meses, parece que GoDaddy podría volver al mercado de adquisiciones para una plataforma como Netlify.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Alguna otra que se te ocurra? Ayudame actulizar este post!! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NXhSWTf8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/khriztianmoreno/image/upload/c_scale%2Cw_148/v1591324337/KM-brand/stickers/sticker-3_2x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NXhSWTf8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/khriztianmoreno/image/upload/c_scale%2Cw_148/v1591324337/KM-brand/stickers/sticker-3_2x.png" alt="Profile" width="148" height="91"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a class="mentioned-user" href="https://dev.to/khriztianmoreno"&gt;@khriztianmoreno&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Hasta la próxima.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>discuss</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Clonar un objeto en JavaScript: 4 mejores formas [Ejemplos]</title>
      <dc:creator>Khriztian Moreno</dc:creator>
      <pubDate>Mon, 23 Jan 2023 21:11:21 +0000</pubDate>
      <link>https://forem.com/khriztianmoreno/clonar-un-objeto-en-javascript-4-mejores-formas-ejemplos-1bke</link>
      <guid>https://forem.com/khriztianmoreno/clonar-un-objeto-en-javascript-4-mejores-formas-ejemplos-1bke</guid>
      <description>&lt;p&gt;Clonar un objeto en JavaScript significa crear una copia idéntica de un objeto existente. Esto significa que el nuevo objeto tendrá los mismos valores para cada propiedad, pero será un objeto diferente.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Por qué es importante clonar un objeto en javascript?
&lt;/h2&gt;

&lt;p&gt;Clonar un objeto en javascript es importante para preservar el estado original de un objeto y evitar la propagación de los cambios. Esto es especialmente útil cuando hay varias instancias de un objeto que se comparten entre varias partes de la aplicación. Clonar el objeto original garantiza que las otras instancias no se vean afectadas por los cambios realizados en el objeto original. Esto también permite a los desarrolladores usar una sola instancia del objeto y crear una copia única para cada parte de la aplicación. Esto evita tener que crear cada vez una nueva instancia del objeto, lo que ahorra tiempo y recursos.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo clonar un objeto?
&lt;/h3&gt;

&lt;p&gt;Para clonar un objeto JavaScript correctamente, tienes 4 opciones diferentes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Usar la función &lt;code&gt;structuredClone()&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Usar el spread operator &lt;/li&gt;
&lt;li&gt;Llamar la función &lt;code&gt;Object.assign()&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Usar JSON parsing.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;khriztianmoreno&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;copy4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;structuredClone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;copy1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;copy2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// 4&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;copy3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1. &lt;code&gt;structuredClone()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Crea un clon profundo de un valor dado utilizando el algoritmo de clonación estructurada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;someProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;with a string value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;anotherProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;withAnotherProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;andAnotherProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myDeepCopy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;structuredClone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. spread operator
&lt;/h3&gt;

&lt;p&gt;El operador de propagación &lt;code&gt;(...)&lt;/code&gt; permite expandir un objeto o un arreglo en una lista de elementos individuales, y se utiliza para crear una copia de un objeto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;khriztianmoreno&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En el ejemplo anterior, se esta creando un nuevo objeto clone a partir de los valores del objeto original, es importante notar que esto solo hace una &lt;strong&gt;copia superficial&lt;/strong&gt;, si el objeto original contiene objetos o arreglos dentro de el, estos no serán clonados sino que se asigna la referencia del objeto original.&lt;/p&gt;

&lt;p&gt;También se puede utilizar para clonar arreglos de la siguiente manera:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. &lt;code&gt;Object.assign&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;La función &lt;code&gt;Object.assign()&lt;/code&gt; es otra forma de clonar objetos en JavaScript. La función toma un objeto destino como primer argumento, y uno o más objetos fuente como argumentos adicionales. Copia las propiedades enumerables de los objetos fuente al objeto destino.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;khriztianmoreno&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. JSON parsing
&lt;/h3&gt;

&lt;p&gt;El método &lt;code&gt;JSON.parse()&lt;/code&gt; y &lt;code&gt;JSON.stringify()&lt;/code&gt; es otra forma de clonar objetos en JavaScript. El método &lt;code&gt;JSON.stringify()&lt;/code&gt; convierte un objeto en una cadena de texto en formato JSON, mientras que el método &lt;code&gt;JSON.parse()&lt;/code&gt; convierte una cadena de texto en formato JSON en un objeto de JavaScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;khriztianmoreno&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusiones
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Ventajas de clonar un objeto en javascript
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;El clonado de objetos permite al desarrollador crear una copia de un objeto existente sin tener que redefinir todos los valores del objeto. Esto significa que el desarrollador puede ahorrar tiempo y esfuerzo al no tener que recrear un objeto desde cero.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;El clonado de objetos también permite al desarrollador crear una versión modificada de un objeto existente. Por ejemplo, un desarrollador puede modificar los valores de un objeto existente para crear una versión personalizada. Esto es útil para ahorrar tiempo al no tener que reescribir el código para crear un objeto desde cero.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;El clonado de objetos también permite al desarrollador crear una versión mejorada de un objeto existente. Por ejemplo, un desarrollador puede añadir nuevas propiedades a un objeto existente para mejorar su funcionalidad.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;El clonado de objetos también ofrece una forma de hacer copias de seguridad de los objetos. Esto significa que si el objeto existente se ve afectado por una falla de software, el desarrollador puede recurrir a la copia de seguridad para recuperar los valores originales.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Desventajas de clonar un objeto en javascript
&lt;/h3&gt;

&lt;p&gt;Clonar un objeto en Javascript puede ser una tarea útil, pero también hay algunos inconvenientes que deben tenerse en cuenta. El primero es el tiempo de ejecución. El clonado de objetos en Javascript puede ser un proceso lento, especialmente si el objeto es grande. Esto puede llevar a una mala experiencia de usuario si se está intentando clonar un objeto mientras se ejecuta una aplicación. &lt;/p&gt;

&lt;p&gt;Otra desventaja del clonado de objetos en Javascript es que no se pueden clonar objetos complejos. Esto significa que los objetos que contienen referencias a otros objetos no se pueden clonar correctamente. Esto puede ser un problema si se está intentando clonar un objeto que contiene referencias a otros objetos importantes, ya que el clon no tendrá estas referencias. &lt;/p&gt;

&lt;p&gt;Por último, el clonado de objetos en Javascript también puede llevar a problemas de seguridad si se clonan objetos que contienen información sensible. El clon puede contener la misma información que el objeto original, lo que puede ser un riesgo para la seguridad si se comparte el clon con otros usuarios.&lt;/p&gt;

&lt;p&gt;¡Eso es todo amigxs! ¡Espero que este artículo lo ayude a comprender las diferentes opciones que tenemos a la hora de clonar un objecto/arraglo en javascript.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rdbt84oh93va3vi70m5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rdbt84oh93va3vi70m5.png" alt="Profile" width="148" height="91"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a class="mentioned-user" href="https://dev.to/khriztianmoreno"&gt;@khriztianmoreno&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Hasta la próxima.&lt;/p&gt;

&lt;p&gt;PD: Este articulo fue escrito completamente usando &lt;a href="https://openai.com/" rel="noopener noreferrer"&gt;Inteligencia Aritifcial&lt;/a&gt; &lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Cómo usar los métodos Call, Apply y Bind en javascript</title>
      <dc:creator>Khriztian Moreno</dc:creator>
      <pubDate>Wed, 28 Sep 2022 15:55:52 +0000</pubDate>
      <link>https://forem.com/khriztianmoreno/como-usar-los-metodos-javascript-call-apply-y-bind-32ek</link>
      <guid>https://forem.com/khriztianmoreno/como-usar-los-metodos-javascript-call-apply-y-bind-32ek</guid>
      <description>&lt;p&gt;En este artículo, veremos qué son los métodos &lt;code&gt;call&lt;/code&gt;, &lt;code&gt;apply&lt;/code&gt; y &lt;code&gt;bind&lt;/code&gt; en javascript y por qué existen.&lt;/p&gt;

&lt;p&gt;Antes de saltar, necesitamos saber que es &lt;code&gt;this&lt;/code&gt; en javascript, en &lt;a href="https://www.freecodecamp.org/espanol/news/la-guia-completa-sobre-this-en-javascript/#:~:text=El%20this%20de%20JavaScript%20es,a%20veces%20se%20llama%20contexto" rel="noopener noreferrer"&gt;este post&lt;/a&gt; puedes profundizar un poco más.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;En Javascript, todas las funciones tendrán acceso a una palabra clave especial llamada &lt;code&gt;this&lt;/code&gt;, el valor de &lt;code&gt;this&lt;/code&gt; apuntará al objeto en el que se ejecuta esa función.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué son estos métodos &lt;code&gt;call&lt;/code&gt;, &lt;code&gt;apply&lt;/code&gt; y &lt;code&gt;bind&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;Para decirlo de una manera simple, todos estos métodos se usan para cambiar el valor de &lt;code&gt;this&lt;/code&gt; dentro de una función.&lt;/p&gt;

&lt;p&gt;Entendamos cada método en detalle.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Function/call" rel="noopener noreferrer"&gt;call()&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Usando el método &lt;code&gt;call&lt;/code&gt;, podemos invocar una función, pasando un valor que será tratado como &lt;code&gt;this&lt;/code&gt; dentro de ella.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;myName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;khriztianmoreno&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;printName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;printName&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// khriztianmoreno&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;myName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mafeserna&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;printName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newObj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//mafeserna&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;en el ejemplo anterior, estamos invocando el método &lt;code&gt;call&lt;/code&gt; en la función &lt;code&gt;printName&lt;/code&gt; al pasar &lt;code&gt;newObj&lt;/code&gt; como parámetro, por lo que ahora &lt;code&gt;this&lt;/code&gt; dentro de &lt;code&gt;printName&lt;/code&gt; apunta a &lt;code&gt;newObj&lt;/code&gt;, por lo tanto, &lt;code&gt;this.myName&lt;/code&gt; imprime &lt;code&gt;mafeserna&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo pasar argumentos a funciones?
&lt;/h3&gt;

&lt;p&gt;El primer argumento del método &lt;code&gt;call&lt;/code&gt; es el valor al que apunta &lt;code&gt;this&lt;/code&gt; dentro de la función, para pasar argumentos adicionales a esa función, podemos comenzar a pasarlo desde el segundo argumento del método &lt;code&gt;call&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;param1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;param2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;thisObj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arg2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;dónde:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;foo&lt;/code&gt; es la función que estamos invocando al pasar el nuevo valor &lt;code&gt;this&lt;/code&gt; que es &lt;code&gt;thisObj&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;arg1&lt;/code&gt;, &lt;code&gt;arg2&lt;/code&gt;, son los argumentos adicionales que tomará la función &lt;code&gt;foo&lt;/code&gt; ( &lt;code&gt;param1&lt;/code&gt;= &lt;code&gt;arg1&lt;/code&gt; , &lt;code&gt;param2&lt;/code&gt; = &lt;code&gt;arg2&lt;/code&gt; )&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Function/apply" rel="noopener noreferrer"&gt;apply()&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;La función &lt;code&gt;apply&lt;/code&gt; es muy similar a la función &lt;code&gt;call&lt;/code&gt;. La única diferencia entre &lt;code&gt;call&lt;/code&gt; y &lt;code&gt;apply&lt;/code&gt; es la diferencia en cómo se pasan los argumentos.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;call&lt;/code&gt; — pasamos argumentos como valores individuales, comenzando desde el segundo argumento&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;apply&lt;/code&gt; — los argumentos adicionales se pasarán como un arreglo&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; ! &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;khriztianmoreno&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Call&lt;/span&gt;
&lt;span class="nx"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Good Morning&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;// Hello khriztianmoreno ! Good Morning&lt;/span&gt;

&lt;span class="c1"&gt;// Apply&lt;/span&gt;
&lt;span class="nx"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Good Morning&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; 
&lt;span class="c1"&gt;// Hello khriztianmoreno ! Good Morning&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;en el ejemplo anterior, tanto el método &lt;code&gt;call&lt;/code&gt; como &lt;code&gt;apply&lt;/code&gt; en la función &lt;code&gt;sayHello&lt;/code&gt; están haciendo lo mismo, la única diferencia es cómo estamos pasando argumentos adicionales.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Function/bind" rel="noopener noreferrer"&gt;bind()&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A diferencia de los métodos &lt;code&gt;call&lt;/code&gt; y &lt;code&gt;apply&lt;/code&gt;, &lt;code&gt;bind&lt;/code&gt; no invocará la función directamente, sino que cambiará el valor &lt;code&gt;this&lt;/code&gt; dentro de la función y devolverá la instancia de la función modificada.&lt;/p&gt;

&lt;p&gt;Podemos invocar la función devuelta más tarde.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;khriztianmoreno&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// it won't invoke, it just returns back the new function instance&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newFunc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

&lt;span class="nf"&gt;newFunc&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// khriztianmoreno&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;pasando argumentos adicionales:&lt;/strong&gt;&lt;br&gt;
pasar argumentos adicionales en &lt;code&gt;bind&lt;/code&gt; funciona de manera similar al método &lt;code&gt;call&lt;/code&gt;, podemos pasar argumentos adicionales como valores individuales a partir del segundo argumento del método &lt;code&gt;bind&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;khriztianmoreno&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newFunc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;newFunc&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Hello khriztianmoreno&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;En el caso del método &lt;code&gt;bind&lt;/code&gt;, podemos pasar argumentos adicionales de dos formas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Al llamar al método &lt;code&gt;bind&lt;/code&gt; en sí mismo, podemos pasar argumentos adicionales junto con el valor de &lt;code&gt;this&lt;/code&gt; a esa función.&lt;/li&gt;
&lt;li&gt;Otra forma es que podemos pasar argumentos adicionales mientras invocamos la función de retorno del método &lt;code&gt;bind&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Podemos seguir cualquiera de las formas anteriores y funciona de manera similar sin ninguna diferencia en la funcionalidad.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;khriztianmoreno&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newFunc1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;newFunc1&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Hello khriztianmoreno&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newFunc2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;newFunc2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Hello khriztianmoreno&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;NOTA&lt;/strong&gt;: &lt;em&gt;si no pasamos ningún valor o pasamos&lt;code&gt;null&lt;/code&gt; mientras llamamos a los métodos &lt;code&gt;call&lt;/code&gt;, &lt;code&gt;apply&lt;/code&gt;, &lt;code&gt;bind&lt;/code&gt;, entonces &lt;code&gt;esta&lt;/code&gt; función interna de llamada apuntará al objeto &lt;code&gt;global&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// executing in browser env&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nx"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nx"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;()();&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;No podemos usar los métodos &lt;code&gt;call&lt;/code&gt;, &lt;code&gt;apply&lt;/code&gt; y &lt;code&gt;bind&lt;/code&gt; en las &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions" rel="noopener noreferrer"&gt;funciones flecha&lt;/a&gt; para cambiar el valor de &lt;code&gt;this&lt;/code&gt;, porque las funciones de flecha no tienen su propio contexto &lt;code&gt;this&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;El &lt;code&gt;this&lt;/code&gt; dentro de la función de flecha apuntará a la función externa/principal en la que está presente.&lt;/p&gt;

&lt;p&gt;Por lo tanto, aplicar estos métodos en la función de flecha no tendrá ningún efecto.&lt;/p&gt;

&lt;p&gt;¡Eso es todo amigxs! ¡Espero que este artículo lo ayude a comprender qué son los métodos &lt;code&gt;call()&lt;/code&gt;, &lt;code&gt;apply()&lt;/code&gt; y &lt;code&gt;bind()&lt;/code&gt; en javascript.!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rdbt84oh93va3vi70m5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rdbt84oh93va3vi70m5.png" alt="Profile"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a class="mentioned-user" href="https://dev.to/khriztianmoreno"&gt;@khriztianmoreno&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Hasta la próxima.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Hacks para un desarrollo Fullstack efectivo con React y Node</title>
      <dc:creator>Khriztian Moreno</dc:creator>
      <pubDate>Thu, 01 Sep 2022 18:45:21 +0000</pubDate>
      <link>https://forem.com/khriztianmoreno/hacks-para-un-desarrollo-fullstack-efectivo-con-react-y-node-2mgi</link>
      <guid>https://forem.com/khriztianmoreno/hacks-para-un-desarrollo-fullstack-efectivo-con-react-y-node-2mgi</guid>
      <description>&lt;p&gt;Hoy te mostraré un flujo de trabajo óptimo para un desarrollo efectivo con Node.js y React. Si alguna vez ha trabajado en un proyecto con varios archivos package.json, es posible que conozca el dolor de hacer malabarismos con varias pestañas de terminal, recordar qué comandos inician qué servidor o manejar los errores de CORS.&lt;/p&gt;

&lt;p&gt;Afortunadamente, hay algunas herramientas disponibles que pueden aliviar algunos de estos dolores de cabeza.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuración de Monorepo para React y Node
&lt;/h2&gt;

&lt;p&gt;Digamos que estamos trabajando en un &lt;a href="https://en.wikipedia.org/wiki/Monorepo" rel="noopener noreferrer"&gt;monorepo &lt;/a&gt;con dos archivos &lt;code&gt;package.json&lt;/code&gt;: uno está en un directorio &lt;code&gt;client&lt;/code&gt; para un front-end de React impulsado por &lt;a href="https://create-react-app.dev/" rel="noopener noreferrer"&gt;Create React App&lt;/a&gt;, y uno está en la raíz del repositorio para un back-end de Node que expone un API que utiliza nuestra aplicación React. Nuestra aplicación React se ejecuta en &lt;code&gt;localhost:3000&lt;/code&gt; y nuestra aplicación Node se ejecuta en &lt;code&gt;localhost:8080&lt;/code&gt;. Ambas aplicaciones se inician con &lt;code&gt;npm start&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Dado que tenemos dos archivos &lt;code&gt;package.json&lt;/code&gt;, esto significa que para que nuestro front-end y back-end estén en funcionamiento, debemos asegurarnos de haber ejecutado &lt;code&gt;npm install&lt;/code&gt; y &lt;code&gt;npm start&lt;/code&gt; tanto en el directorio raíz como en el directorio del cliente. Así es como simplificamos esto.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Ejecutar dos servidores al mismo tiempo
&lt;/h2&gt;

&lt;p&gt;Una mejora que podemos hacer en nuestro flujo de trabajo de desarrollo es agregar una herramienta de compilación para ejecutar varios comandos &lt;strong&gt;npm&lt;/strong&gt; al mismo tiempo para ahorrarnos la molestia de ejecutar &lt;code&gt;npm start&lt;/code&gt; en varias pestañas de terminal. Para hacer esto, podemos agregar un paquete npm llamado &lt;a href="https://www.npmjs.com/package/concurrently" rel="noopener noreferrer"&gt;concurrently&lt;/a&gt; a la raíz de nuestro proyecto.&lt;/p&gt;

&lt;p&gt;En la raíz de nuestro proyecto, lo instalaremos como una dependencia de desarrollo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; concurrently
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Luego, en nuestras secuencias de comandos root &lt;code&gt;package.json&lt;/code&gt;, actualizaremos nuestra secuencia de comandos &lt;code&gt;start&lt;/code&gt; para usarlas simultáneamente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"concurrently --kill-others-on-fail npm run server npm run client"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"server"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"client"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cd client &amp;amp;&amp;amp; npm start"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"express"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^4.17.1"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"concurrently"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^6.0.1"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora, tenemos tres scripts npm:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;npm run server&lt;/code&gt; inicia nuestra aplicación Node,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm run client&lt;/code&gt; ejecuta &lt;code&gt;npm start&lt;/code&gt; en el directorio del &lt;em&gt;client&lt;/em&gt; para iniciar nuestra aplicación React,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm start&lt;/code&gt; ejecuta &lt;code&gt;npm run server&lt;/code&gt; y &lt;code&gt;npm run client&lt;/code&gt; al mismo tiempo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Instalar las dependencias de front-end y back-end con un solo comando
&lt;/h2&gt;

&lt;p&gt;Otro aspecto de nuestro flujo de trabajo que podemos mejorar es la instalación de dependencias. Actualmente, necesitamos ejecutar manualmente &lt;code&gt;npm install&lt;/code&gt; para cada archivo &lt;code&gt;package.json&lt;/code&gt; que tenemos al configurar el proyecto. En lugar de pasar por esa molestia, podemos agregar un &lt;a href="https://docs.npmjs.com/cli/v7/using-npm/scripts" rel="noopener noreferrer"&gt;postinstall script&lt;/a&gt; a nuestro &lt;code&gt;package.json&lt;/code&gt; raiz para ejecutar automáticamente &lt;code&gt;npm install&lt;/code&gt; en el directorio del &lt;em&gt;client&lt;/em&gt; después de que la instalación haya finalizado en el directorio raíz.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"postinstall"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cd client &amp;amp;&amp;amp; npm install"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora, cuando instalamos nuestro monorepo, todo lo que tenemos que hacer para ponerlo en marcha es ejecutar &lt;code&gt;npm install&lt;/code&gt; y luego &lt;code&gt;npm start&lt;/code&gt; en la raíz del proyecto. No es necesario ingresar a ningún otro directorio para ejecutar otros comandos.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Solicitudes API proxy desde el back-end
&lt;/h2&gt;

&lt;p&gt;Como mencione anteriormente, nuestro back-end de Node expone los endpoints del API que utilizara nuestra aplicación React. Digamos que nuestra aplicación Node tiene un endpoint &lt;code&gt;/refresh_token&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Fuera de la caja, si intentáramos enviar una solicitud GET a &lt;code&gt;http://localhost:8080/refresh_token&lt;/code&gt; desde nuestra aplicación React en &lt;code&gt;http://localhost:3000&lt;/code&gt;, nos encontraríamos con problemas de CORS. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" rel="noopener noreferrer"&gt;CORS&lt;/a&gt; significa intercambio de recursos de origen cruzado.&lt;/p&gt;

&lt;p&gt;Por lo general, cuando encuentra errores de CORS, es porque está tratando de acceder a los recursos de otro dominio (es decir, &lt;code&gt;http://localhost:3000&lt;/code&gt; y &lt;code&gt;http://localhost:8080&lt;/code&gt;), y el dominio del que está solicitando recursos no está permitido. &lt;/p&gt;

&lt;p&gt;Para decirle al servidor de desarrollo que envíe por proxy cualquier solicitud desconocida a nuestro servidor API en desarrollo, podemos configurar un &lt;a href="https://create-react-app.dev/docs/proxying-api-requests-in-development" rel="noopener noreferrer"&gt;proxy&lt;/a&gt; en el archivo &lt;code&gt;package.json&lt;/code&gt; de nuestra aplicación React. En &lt;code&gt;client/package.json&lt;/code&gt;, agregaremos un proxy para &lt;code&gt;http://localhost:8080&lt;/code&gt; (donde se ejecuta nuestra aplicación Node).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"client-app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"proxy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"react"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^18.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"react-dom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^18.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"react-scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5.0.1"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-scripts start"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-scripts build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-scripts test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"eject"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-scripts eject"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora, si reiniciamos el servidor y configuramos una solicitud al endPoint &lt;code&gt;/refresh_token&lt;/code&gt; de nuestra aplicación Node (sin &lt;code&gt;http://localhost:8080&lt;/code&gt;) usando &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch" rel="noopener noreferrer"&gt;fetch()&lt;/a&gt;, el error CORS debería resolverse.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/refresh_token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La próxima vez que trabaje en un proyecto monorepo como este, pruebe estos tres consejos para optimizar su flujo de trabajo de desarrollo.&lt;/p&gt;

&lt;p&gt;¡Eso es todo amigxs! ¡Espero que esto te ayude a convertirte en un o una mejor dev!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rdbt84oh93va3vi70m5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rdbt84oh93va3vi70m5.png" alt="Profile"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a class="mentioned-user" href="https://dev.to/khriztianmoreno"&gt;@khriztianmoreno&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Hasta la próxima.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>react</category>
      <category>node</category>
    </item>
  </channel>
</rss>
