<?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>DEV Community: Erick Eduardo Ramos</title>
    <description>The latest articles on DEV Community by Erick Eduardo Ramos (@erickeduardoramos03).</description>
    <link>https://dev.to/erickeduardoramos03</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3943545%2Ff8b96fcc-b7e6-4c21-a809-3c6ffedaea58.png</url>
      <title>DEV Community: Erick Eduardo Ramos</title>
      <link>https://dev.to/erickeduardoramos03</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/erickeduardoramos03"/>
    <language>en</language>
    <item>
      <title>Cómo solucionar el error “Text content does not match server-rendered HTML” en Next.js App Router</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Wed, 22 Jul 2026 11:01:56 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-el-error-text-content-does-not-match-server-rendered-html-en-nextjs-app-router-5893</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-el-error-text-content-does-not-match-server-rendered-html-en-nextjs-app-router-5893</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar el error “Text content does not match server-rendered HTML” en Next.js App Router
&lt;/h1&gt;

&lt;p&gt;Este error ocurre cuando el HTML generado en el servidor (SSR/SSG) no coincide con el árbol de React generado durante la primera renderización en el cliente (hydration). React detecta una inconsistencia crítica y detiene la hidratación para evitar comportamientos impredecibles.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔍 Causa raíz (en tu caso específico)
&lt;/h2&gt;

&lt;p&gt;Dado que mencionas &lt;strong&gt;"Latest Version 16.2.11"&lt;/strong&gt; y el contexto de App Router, es muy probable que estés usando &lt;strong&gt;&lt;code&gt;Date()&lt;/code&gt; o &lt;code&gt;new Date()&lt;/code&gt; directamente en el render de un componente&lt;/strong&gt;, o alguna dependencia (como una librería de UI o un hook personalizado) que lo haga.&lt;/p&gt;

&lt;p&gt;Ejemplo típico:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Mala práctica: Date() se evalúa en SSR y en CSR, pero con microdiferencias de tiempo&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Timestamp&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;time&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&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;time&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;p&gt;Otra causa común: &lt;strong&gt;iOS Safari modifica el DOM inyectando enlaces automáticamente en lo que detecta como números de teléfono o fechas&lt;/strong&gt;, lo cual rompe la consistencia entre SSR y CSR.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Solución definitiva (pasos)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Paso 1: Aísla la fuente del desajuste
&lt;/h3&gt;

&lt;p&gt;Busca en tu código (especialmente en &lt;code&gt;app/&lt;/code&gt;, &lt;code&gt;layout.tsx&lt;/code&gt;, &lt;code&gt;page.tsx&lt;/code&gt;, componentes reutilizables) cualquier uso de:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;new Date()&lt;/code&gt;, &lt;code&gt;Date.now()&lt;/code&gt;, &lt;code&gt;Math.random()&lt;/code&gt;, &lt;code&gt;window&lt;/code&gt;, &lt;code&gt;localStorage&lt;/code&gt;, &lt;code&gt;navigator&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;Librerías que usan APIs del navegador sin protección (ej. &lt;code&gt;framer-motion&lt;/code&gt;, &lt;code&gt;react-icons&lt;/code&gt; sin &lt;code&gt;ssr: false&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Paso 2: Aplica la solución correcta según el caso
&lt;/h3&gt;

&lt;h4&gt;
  
  
  🔹 Caso A: Contenido dinámico &lt;em&gt;intencionalmente diferente&lt;/em&gt; (ej. timestamps, UUIDs)
&lt;/h4&gt;

&lt;p&gt;Usa &lt;code&gt;suppressHydrationWarning&lt;/code&gt; &lt;strong&gt;solo en el elemento afectado&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Correcto: suprime advertencia *solo* en el elemento problemático&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;time&lt;/span&gt; 
  &lt;span class="na"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
  &lt;span class="na"&gt;suppressHydrationWarning&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&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;time&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Importante&lt;/strong&gt;: No envuelvas el componente padre en &lt;code&gt;suppressHydrationWarning&lt;/code&gt;, solo el elemento con contenido inestable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  🔹 Caso B: Uso de APIs del navegador (ej. &lt;code&gt;window&lt;/code&gt;, &lt;code&gt;localStorage&lt;/code&gt;)
&lt;/h4&gt;

&lt;p&gt;Mueve la lógica al &lt;code&gt;useEffect&lt;/code&gt; o usa &lt;code&gt;dynamic&lt;/code&gt; con &lt;code&gt;ssr: false&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Opción 1: Con `useEffect`&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ClientOnlyTimestamp&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;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setDate&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&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;setDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;time&lt;/span&gt; &lt;span class="na"&gt;suppressHydrationWarning&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;date&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;time&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 tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Opción 2: Con `dynamic` (recomendado para componentes completos)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;dynamic&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;next/dynamic&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;ClientOnlyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./ClientOnlyComponent&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="na"&gt;ssr&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="na"&gt;loading&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Cargando...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ClientOnlyComponent&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;h4&gt;
  
  
  🔹 Caso C: iOS Safari inyecta enlaces en fechas/teléfonos
&lt;/h4&gt;

&lt;p&gt;Agrega esta etiqueta &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; en tu &lt;code&gt;app/layout.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/layout.tsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;RootLayout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&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;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"es"&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;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="nt"&gt;meta&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"format-detection"&lt;/span&gt;
          &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"telephone=no, date=no, email=no, address=no"&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;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="nt"&gt;body&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;children&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;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="nt"&gt;html&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Paso 3: Verifica configuraciones de infraestructura
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare Auto Minify&lt;/strong&gt;: Desactívalo temporalmente para descartar que el minificador de HTML esté alterando el markup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CDNs o proxies intermedios&lt;/strong&gt;: Algunos inyectan scripts o modifican atributos &lt;code&gt;data-*&lt;/code&gt; o &lt;code&gt;class&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠 Bloque de código corregido (ejemplo real)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/page.tsx&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;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&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="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&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;currentTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCurrentTime&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&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;setCurrentTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleTimeString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;es-ES&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="na"&gt;hour&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2-digit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;minute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2-digit&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;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;main&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"p-4"&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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Última actualización&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&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="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Hora del servidor (estática): 14:30
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Hora del cliente (dinámica):
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;time&lt;/span&gt; &lt;span class="na"&gt;suppressHydrationWarning&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;currentTime&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;time&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;p&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;main&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💡 Pro-tip: Prevención a largo plazo
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Usa linter con reglas de React&lt;/strong&gt;: Instala &lt;code&gt;eslint-plugin-react-hooks&lt;/code&gt; y &lt;code&gt;eslint-plugin-jsx-a11y&lt;/code&gt;. Detectan usos peligrosos de &lt;code&gt;Date()&lt;/code&gt; o &lt;code&gt;window&lt;/code&gt; en render.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prueba en modo desarrollo&lt;/strong&gt;: El error aparece en consola con &lt;code&gt;React hydration error&lt;/code&gt;, pero &lt;strong&gt;no aparece en producción&lt;/strong&gt; (solo silenciosamente falla). Siempre desarrolla con &lt;code&gt;next dev&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evita lógica de render condicional basada en &lt;code&gt;typeof window&lt;/code&gt;&lt;/strong&gt;: Usa &lt;code&gt;useEffect&lt;/code&gt; o &lt;code&gt;dynamic({ ssr: false })&lt;/code&gt; en su lugar.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;✅ &lt;strong&gt;Verificación final&lt;/strong&gt;: Si el error desaparece al deshabilitar JavaScript, el problema es de hidratación. Si persiste, revisa tu HTML generado (View Source vs DevTools Elements).&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>nextjs</category>
      <category>react</category>
    </item>
    <item>
      <title>Cómo solucionar el error de permiso al ejecutar `pip.exe` en un entorno virtual de Python en Windows</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Tue, 21 Jul 2026 11:00:52 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-el-error-de-permiso-al-ejecutar-pipexe-en-un-entorno-virtual-de-python-en-windows-42ci</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-el-error-de-permiso-al-ejecutar-pipexe-en-un-entorno-virtual-de-python-en-windows-42ci</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar el error de permiso al ejecutar &lt;code&gt;pip.exe&lt;/code&gt; en un entorno virtual de Python en Windows
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Explicación técnica
&lt;/h2&gt;

&lt;p&gt;El error ocurre porque &lt;code&gt;pip.exe&lt;/code&gt; en el entorno virtual es un &lt;em&gt;launcher&lt;/em&gt; empaquetado (un archivo &lt;code&gt;.exe&lt;/code&gt; que contiene una copia embebida de &lt;code&gt;python.exe&lt;/code&gt; y el script &lt;code&gt;__main__.py&lt;/code&gt; de pip). Este launcher almacena una ruta fija a &lt;code&gt;python.exe&lt;/code&gt; en su interior. Cuando se crea el entorno virtual, el launcher se configura con la ruta exacta del &lt;code&gt;python.exe&lt;/code&gt; usado para crearlo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Causa raíz&lt;/strong&gt;: Si has reinstalado Python (especialmente si pasaste de instalador oficial a Microsoft Store, o viceversa), o si el &lt;code&gt;python.exe&lt;/code&gt; original ya no existe en la ruta original (por ejemplo, si desinstalaste Python 3.10.11), el launcher de &lt;code&gt;pip.exe&lt;/code&gt; sigue apuntando a una ruta rota o inaccesible. Esto provoca el error &lt;em&gt;“Access is denied”&lt;/em&gt; al intentar ejecutarlo directamente, aunque &lt;code&gt;python -m pip&lt;/code&gt; funcione (porque usa el &lt;code&gt;python.exe&lt;/code&gt; actual del PATH, no el embebido).&lt;/p&gt;




&lt;h2&gt;
  
  
  Pasos para solucionarlo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Verifica la ruta embebida en &lt;code&gt;pip.exe&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Crea un script temporal (&lt;code&gt;check_pip_launcher.py&lt;/code&gt;) con el siguiente contenido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Uso: python check_pip_launcher.py &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;path&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;pip.exe&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&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="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rb&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rfind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PK&lt;/span&gt;&lt;span class="se"&gt;\x05\x06&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;i0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rfind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#!&lt;/span&gt;&lt;span class="sh"&gt;'&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="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;i1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ruta embebida en pip.exe: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error al leer pip.exe: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ejecútalo &lt;strong&gt;desde CMD (no desde Bash)&lt;/strong&gt; y &lt;strong&gt;sin activar el entorno virtual&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python check_pip_launcher.py "C:\Users\&amp;lt;username&amp;gt;\tu-proyecto\venv\Scripts\pip.exe"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ Si obtienes &lt;em&gt;“Access is denied”&lt;/em&gt; aquí también, el problema es más profundo (falta de permisos o archivo corrupto). Ve al paso 3.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. Si la ruta embebida es inválida (archivo inexistente o con permisos incorrectos)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solución definitiva&lt;/strong&gt;: Recrea el entorno virtual con el &lt;code&gt;python.exe&lt;/code&gt; correcto.&lt;/p&gt;

&lt;h4&gt;
  
  
  Opción A (recomendada): Elimina y recrea el entorno
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Desde CMD (no Bash), en la raíz del proyecto
rmdir /s /q venv
python -m venv venv
venv\Scripts\activate
pip install -e .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;✅ Esto garantiza que &lt;code&gt;pip.exe&lt;/code&gt; se genere con la ruta correcta al &lt;code&gt;python.exe&lt;/code&gt; actual.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Opción B (si no puedes borrar el entorno): Reemplaza &lt;code&gt;pip.exe&lt;/code&gt; manualmente
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Copia &lt;code&gt;python.exe&lt;/code&gt; desde tu entorno virtual a una ubicación temporal (ej: &lt;code&gt;venv\Scripts\python_backup.exe&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Descarga el último &lt;code&gt;pip&lt;/code&gt; como archivo &lt;code&gt;.whl&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   python -m pip install --upgrade pip --target venv\Lib\site-packages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Usa &lt;code&gt;pip.exe&lt;/code&gt; de otro entorno funcional como plantilla (opcional), o simplemente ejecuta:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   python -m pip install --force-reinstall pip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto regenera los launchers (&lt;code&gt;pip.exe&lt;/code&gt;, &lt;code&gt;pip3.exe&lt;/code&gt;, etc.) con la ruta correcta.&lt;/p&gt;




&lt;h2&gt;
  
  
  Bloque de código corregido (comando final)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:: Elimina el entorno roto y recrea con el python correcto
rmdir /s /q venv
python -m venv venv
call venv\Scripts\activate.bat
pip install --upgrade pip
pip install -e .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🔁 &lt;strong&gt;Nota&lt;/strong&gt;: Usa &lt;code&gt;call&lt;/code&gt; para asegurar que el &lt;code&gt;activate.bat&lt;/code&gt; se ejecute en el mismo contexto de CMD y no termine la sesión.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Pro-tip: Evita este problema en el futuro
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nunca mezcles instaladores de Python y Microsoft Store&lt;/strong&gt;: Si usas el Microsoft Store, usa &lt;code&gt;py -3.10 -m venv venv&lt;/code&gt; para crear entornos con la versión específica.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa &lt;code&gt;python -m pip&lt;/code&gt; siempre que sea posible&lt;/strong&gt;: Es más robusto que &lt;code&gt;pip&lt;/code&gt;, ya que no depende del launcher y usa el &lt;code&gt;python.exe&lt;/code&gt; del entorno activo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verifica la integridad del launcher&lt;/strong&gt;: Si el error reaparece tras reinstalar Python, ejecuta:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  python -c "import sys; print(sys.executable)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;y asegúrate de que coincida con la ruta embebida en &lt;code&gt;pip.exe&lt;/code&gt; (verifica con el script del paso 1).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Heurística rápida&lt;/strong&gt;: Si &lt;code&gt;python -m pip&lt;/code&gt; funciona pero &lt;code&gt;pip&lt;/code&gt; no, el problema es &lt;strong&gt;siempre&lt;/strong&gt; el launcher (&lt;code&gt;pip.exe&lt;/code&gt;), no pip en sí.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>cli</category>
      <category>debugging</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Cómo solucionar el error de permisos al ejecutar `pip.exe` en un entorno virtual de Python en Windows</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Mon, 20 Jul 2026 11:39:04 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-el-error-de-permisos-al-ejecutar-pipexe-en-un-entorno-virtual-de-python-en-bmm</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-el-error-de-permisos-al-ejecutar-pipexe-en-un-entorno-virtual-de-python-en-bmm</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar el error de permisos al ejecutar &lt;code&gt;pip.exe&lt;/code&gt; en un entorno virtual de Python en Windows
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Explicación técnica
&lt;/h2&gt;

&lt;p&gt;El problema ocurre porque el archivo &lt;code&gt;pip.exe&lt;/code&gt; en &lt;code&gt;venv/Scripts/&lt;/code&gt; es un &lt;em&gt;launcher&lt;/em&gt; empaquetado que contiene una ruta fija a &lt;code&gt;python.exe&lt;/code&gt; y un script &lt;code&gt;__main__.py&lt;/code&gt; incrustado. Cuando se crea el entorno virtual, este launcher se construye con la ruta exacta al &lt;code&gt;python.exe&lt;/code&gt; que se usó para crearlo.&lt;/p&gt;

&lt;p&gt;Si esa ruta original ya no existe (por ejemplo, porque desinstalaste Python 3.10.11 y ahora solo tienes 3.10.11 instalado desde Microsoft Store —con una ruta diferente—), el launcher sigue apuntando a una ubicación inválida. Al intentar ejecutarlo, Windows devuelve &lt;strong&gt;"Access is denied"&lt;/strong&gt;, aunque técnicamente el problema no es de permisos, sino de &lt;strong&gt;ruta rota en el launcher&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Este comportamiento es típico cuando:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Se cambia la versión de Python o su ubicación (instalación local vs Microsoft Store).&lt;/li&gt;
&lt;li&gt;Se mueve o renombra el entorno virtual.&lt;/li&gt;
&lt;li&gt;Hay conflictos entre instalaciones de Python de distintas fuentes (python.org vs Microsoft Store).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Pasos para solucionarlo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Verifica si el problema es el launcher roto
&lt;/h3&gt;

&lt;p&gt;Ejecuta en CMD (¡no en bash!):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"C:\Users\&amp;lt;username&amp;gt;\&amp;lt;project dir&amp;gt;\venv\Scripts\pip.exe" -V
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si obtienes &lt;code&gt;Access is denied&lt;/code&gt;, el launcher está roto.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Recrea el entorno virtual (solución definitiva)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;No intentes reparar el launcher manualmente.&lt;/strong&gt; Es más rápido y confiable recrear el entorno.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Desactiva el entorno si está activo
deactivate

# Elimina el entorno actual
rmdir /s /q venv

# Crea uno nuevo con la versión correcta de Python
python -m venv venv

# Activa el entorno
venv\Scripts\activate

# Verifica que pip funcione
pip --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;✅ &lt;strong&gt;Nota crítica&lt;/strong&gt;: Usa &lt;code&gt;python -m venv&lt;/code&gt; desde el intérprete que &lt;em&gt;quieres usar en producción&lt;/em&gt;, no desde otro instalado por Microsoft Store si no es el que usas en CI/CD.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3. Si no puedes recrear el entorno (casos extremos)
&lt;/h3&gt;

&lt;p&gt;Si por alguna razón no puedes borrar el entorno actual, &lt;strong&gt;reemplaza manualmente el launcher&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Copia pip.exe desde otro entorno funcional
copy "C:\otro\entorno\Scripts\pip.exe" "C:\tu\proyecto\venv\Scripts\pip.exe"

# O mejor aún, regenera solo los launchers con:
python -m pip install --upgrade pip --force-reinstall
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Importante&lt;/strong&gt;: El comando anterior &lt;em&gt;solo&lt;/em&gt; funciona si &lt;code&gt;python -m pip&lt;/code&gt; funciona. Si no, usa el método de recrear el entorno.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Bloque de código corregido (script de diagnóstico)
&lt;/h2&gt;

&lt;p&gt;Si necesitas inspeccionar la ruta rota en &lt;code&gt;pip.exe&lt;/code&gt; (solo para diagnóstico), usa este script en CMD:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# save as check_pip_launcher.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&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;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rb&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rfind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PK&lt;/span&gt;&lt;span class="se"&gt;\x05\x06&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;i0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rfind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#!&lt;/span&gt;&lt;span class="sh"&gt;'&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="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
        &lt;span class="n"&gt;i1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Embedded python.exe path: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error reading launcher: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python check_pip_launcher.py "C:\tu\proyecto\venv\Scripts\pip.exe"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si la ruta mostrada no existe (ej. &lt;code&gt;C:\Python310\python.exe&lt;/code&gt; pero ahora Python está en &lt;code&gt;C:\Users\...\AppData\Local\Programs\Python\Python310\python.exe&lt;/code&gt;), el launcher está roto.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pro-tip: Evita futuros problemas con launchers rotos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Usa siempre la misma fuente de Python&lt;/strong&gt; (python.org &lt;em&gt;o&lt;/em&gt; Microsoft Store, no ambas).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nunca muevas el entorno virtual&lt;/strong&gt; (&lt;code&gt;venv&lt;/code&gt; no es portable).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;En scripts de CI/CD&lt;/strong&gt;, usa siempre &lt;code&gt;python -m pip&lt;/code&gt; en lugar de &lt;code&gt;pip.exe&lt;/code&gt; para evitar dependencia del launcher:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="c"&gt;# En lugar de:&lt;/span&gt;
  pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;

  &lt;span class="c"&gt;# Usa:&lt;/span&gt;
  python &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Verifica la integridad del entorno&lt;/strong&gt; antes de usarlo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  python -c "import sys; print(sys.executable)"
  # Debe mostrar: C:\...\venv\Scripts\python.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🔑 &lt;strong&gt;Conclusión&lt;/strong&gt;: El error no es de permisos reales, sino de un &lt;em&gt;launcher corrupto&lt;/em&gt; por cambio de ruta de &lt;code&gt;python.exe&lt;/code&gt;. La única solución robusta es recrear el entorno con la versión correcta de Python.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>debugging</category>
      <category>python</category>
      <category>tooling</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Cómo solucionar el bucle infinito en `useEffect` con objetos y arrays</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Sun, 19 Jul 2026 10:21:35 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-el-bucle-infinito-en-useeffect-con-objetos-y-arrays-57l9</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-el-bucle-infinito-en-useeffect-con-objetos-y-arrays-57l9</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar el bucle infinito en &lt;code&gt;useEffect&lt;/code&gt; con objetos y arrays
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Explicación técnica (por qué ocurre)
&lt;/h2&gt;

&lt;p&gt;El problema ocurre porque &lt;strong&gt;React compara los dependencies del &lt;code&gt;useEffect&lt;/code&gt; usando comparación &lt;code&gt;===&lt;/code&gt; (igualdad estricta)&lt;/strong&gt;, no una comparación profunda del contenido.&lt;/p&gt;

&lt;p&gt;Cuando haces:&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;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setObj&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="nf"&gt;useEffect&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;setObj&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cada vez que &lt;code&gt;setObj({})&lt;/code&gt; se ejecuta, &lt;strong&gt;crea un nuevo objeto en memoria&lt;/strong&gt;. Aunque el contenido parece idéntico, &lt;code&gt;{} !== {}&lt;/code&gt; siempre es &lt;code&gt;true&lt;/code&gt;. Por lo tanto:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;useEffect&lt;/code&gt; detecta que &lt;code&gt;obj&lt;/code&gt; ha cambiado (nueva referencia)&lt;/li&gt;
&lt;li&gt;Ejecuta la callback → &lt;code&gt;setObj({})&lt;/code&gt; crea otro nuevo objeto&lt;/li&gt;
&lt;li&gt;React vuelve a detectar cambio de referencia → bucle infinito&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Solución definitiva (3 enfoques prácticos)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ Opción 1: Evita el ciclo usando dependencias vacías (si solo necesitas ejecutar al montar)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&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;setIngredients&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;// Solo se ejecuta una vez al montar el componente&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✅ Opción 2: Usa comparación profunda con &lt;code&gt;JSON.stringify&lt;/code&gt; (para efectos que dependen del contenido)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&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;// Solo ejecutar si el contenido de ingredients ha cambiado&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;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;ingredients&lt;/span&gt;&lt;span class="p"&gt;)&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;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prevIngredientsRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Tu lógica aquí&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;ingredients&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Nota&lt;/strong&gt;: &lt;code&gt;JSON.stringify&lt;/code&gt; tiene limitaciones (no preserva funciones, &lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;Symbol&lt;/code&gt;, orden de claves no garantizado). Úsalo solo para objetos simples.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  ✅ Opción 3: Usa &lt;code&gt;useReducer&lt;/code&gt; + estado inmutable (recomendado para lógica compleja)
&lt;/h3&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;initialState&lt;/span&gt; &lt;span class="o"&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;reducer&lt;/span&gt; &lt;span class="o"&gt;=&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;action&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;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reset&lt;/span&gt;&lt;span class="dl"&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="c1"&gt;// Devuelve nuevo objeto, pero controlado&lt;/span&gt;
    &lt;span class="nl"&gt;default&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;state&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;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&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;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reset&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="c1"&gt;// O con lógica específica según tu caso&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bloque de código corregido (ejemplo práctico)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Antes (bucle infinito):&lt;/strong&gt;&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;ingredients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIngredients&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="nf"&gt;useEffect&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;setIngredients&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Crea nuevo objeto → bucle infinito&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Referencia cambia siempre&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Después (solución limpia):&lt;/strong&gt;&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;ingredients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIngredients&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="nf"&gt;useEffect&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;// ✅ Solo resetear si no está vacío (evita ciclos innecesarios)&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&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;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIngredients&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="nx"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pro-tip: Patrón para evitar este error en producción
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Nunca uses objetos/arrays literales como dependencias directas&lt;/strong&gt; (&lt;code&gt;[{}]&lt;/code&gt;, &lt;code&gt;[[]]&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa &lt;code&gt;useRef&lt;/code&gt; para valores que no deben desencadenar re-renders&lt;/strong&gt;:
&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;ingredientsRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
   &lt;span class="nf"&gt;useEffect&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;ingredientsRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt; &lt;span class="c1"&gt;// Modifica sin causar re-renders&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;ol&gt;
&lt;li&gt;
&lt;strong&gt;Para objetos complejos, usa librerías como &lt;code&gt;immer&lt;/code&gt; o &lt;code&gt;useDeepCompareEffect&lt;/code&gt;&lt;/strong&gt; (de &lt;code&gt;use-deep-compare-effect&lt;/code&gt;):
&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;useDeepCompareEffect&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;use-deep-compare-effect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="nf"&gt;useDeepCompareEffect&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;setIngredients&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;ingredients&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// ✅ Compara contenido, no referencias&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🔥 &lt;strong&gt;Regla de oro&lt;/strong&gt;: Si tu &lt;code&gt;useEffect&lt;/code&gt; modifica el mismo estado que usa como dependencia, &lt;strong&gt;siempre&lt;/strong&gt; debes verificar si el cambio es necesario antes de llamar al setter.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>debugging</category>
      <category>javascript</category>
      <category>react</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Cómo solucionar `docker run` con exit code 1 en Raspberry Pi</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Sat, 18 Jul 2026 10:13:23 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-docker-run-con-exit-code-1-en-raspberry-pi-31ka</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-docker-run-con-exit-code-1-en-raspberry-pi-31ka</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar &lt;code&gt;docker run&lt;/code&gt; con exit code 1 en Raspberry Pi
&lt;/h1&gt;

&lt;h2&gt;
  
  
  ¿Por qué ocurre?
&lt;/h2&gt;

&lt;p&gt;El error &lt;code&gt;Exited (1)&lt;/code&gt; indica que el proceso principal del contenedor terminó con un código de error no cero. En tu caso específico, el problema &lt;strong&gt;no es el código de error en sí&lt;/strong&gt;, sino que estás usando una sintaxis inválida en el comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--net&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage
&lt;span class="c"&gt;#            ^^^^ ¡Espacios alrededor del '='!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker interpreta &lt;code&gt;--net = host&lt;/code&gt; como dos argumentos separados: &lt;code&gt;--net&lt;/code&gt; y &lt;code&gt;=&lt;/code&gt;, y luego &lt;code&gt;host&lt;/code&gt; como un argumento suelto. Esto hace que Docker no reconozca la red y falle silenciosamente al iniciar el contenedor, causando el &lt;code&gt;exit code 1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Este error es especialmente común en Raspberry Pi porque:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El shell por defecto (&lt;code&gt;bash&lt;/code&gt; o &lt;code&gt;sh&lt;/code&gt;) es estricto con la sintaxis.&lt;/li&gt;
&lt;li&gt;Al ejecutar en modo detached (&lt;code&gt;-d&lt;/code&gt;), no ves los mensajes de error inmediatos.&lt;/li&gt;
&lt;li&gt;La máquina virtual puede tener una configuración diferente (shell, versión de Docker, etc.) que oculta el problema.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Pasos para solucionarlo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Corrige la sintaxis del comando
&lt;/h3&gt;

&lt;p&gt;Elimina los espacios alrededor del signo &lt;code&gt;=&lt;/code&gt; en las opciones de Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage
&lt;span class="c"&gt;#            ^^^^ Sin espacios&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Verifica la versión de Docker en Raspberry Pi
&lt;/h3&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si estás usando una versión muy antigua (&amp;lt; 1.13), considera actualizarla:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade docker.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Ejecuta en primer plano para depurar
&lt;/h3&gt;

&lt;p&gt;Antes de usar &lt;code&gt;-d&lt;/code&gt;, prueba sin él para ver el error en tiempo real:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-t&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si el contenedor necesita un proceso de fondo (como un servidor), asegúrate de que el comando principal sea persistente (no termine inmediatamente).&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Usa &lt;code&gt;docker logs&lt;/code&gt; para confirmar
&lt;/h3&gt;

&lt;p&gt;Después de ejecutar el comando corregido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage
docker ps &lt;span class="nt"&gt;-a&lt;/span&gt;  &lt;span class="c"&gt;# Verifica el ID del contenedor&lt;/span&gt;
docker logs &amp;lt;container_id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Bloque de código corregido
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Comando original con error (¡NO USAR):&lt;/span&gt;
&lt;span class="c"&gt;# docker run --net = host -d -t myimage&lt;/span&gt;

&lt;span class="c"&gt;# Comando corregido:&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage

&lt;span class="c"&gt;# Si el contenedor sigue fallando, depura así:&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-t&lt;/span&gt; myimage  &lt;span class="c"&gt;# Sin -d para ver logs en vivo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Pro-tip: Automatiza la validación de sintaxis
&lt;/h2&gt;

&lt;p&gt;Crea un script de validación para evitar este error en el futuro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# validate-docker-run.sh&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ &lt;span class="s2"&gt;"--net&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="s2"&gt;*=&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="s2"&gt;*"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"⚠️  ERROR: Elimina los espacios alrededor del '=' en --net"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Ejemplo: --net=host (¡sin espacios!)"&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi
&lt;/span&gt;docker run &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Guarda como &lt;code&gt;validate-docker-run.sh&lt;/code&gt;, hazlo ejecutable (&lt;code&gt;chmod +x validate-docker-run.sh&lt;/code&gt;) y úsalo como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./validate-docker-run.sh &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota crítica&lt;/strong&gt;: En Raspberry Pi, siempre usa &lt;code&gt;--net=host&lt;/code&gt; (sin espacios). Este es un error tan común que incluso aparece en foros oficiales de Docker. La solución es 100% sintáctica, no técnica.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>beginners</category>
      <category>debugging</category>
      <category>docker</category>
      <category>iot</category>
    </item>
    <item>
      <title>Cómo solucionar el bucle infinito en useEffect con objetos y arrays</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Fri, 17 Jul 2026 10:40:40 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-el-bucle-infinito-en-useeffect-con-objetos-y-arrays-27h</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-el-bucle-infinito-en-useeffect-con-objetos-y-arrays-27h</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar el bucle infinito en useEffect con objetos y arrays
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Explicación técnica
&lt;/h2&gt;

&lt;p&gt;El problema ocurre porque &lt;strong&gt;React compara las dependencias del &lt;code&gt;useEffect&lt;/code&gt; usando comparación de referencia (&lt;code&gt;===&lt;/code&gt;), no por valor&lt;/strong&gt;. Cuando usas &lt;code&gt;useState({})&lt;/code&gt;, cada llamada a &lt;code&gt;setObj({})&lt;/code&gt; crea un &lt;strong&gt;nuevo objeto en memoria&lt;/strong&gt;, aunque tenga el mismo contenido. Al pasar &lt;code&gt;[obj]&lt;/code&gt; como dependencia, React detecta que la referencia del objeto cambia en cada render (porque es un objeto distinto), lo que dispara el &lt;code&gt;useEffect&lt;/code&gt; de nuevo, creando un bucle infinito.&lt;/p&gt;

&lt;p&gt;Este comportamiento es intencional: los objetos y arrays son tipos por referencia en JavaScript, y React no hace &lt;em&gt;deep comparison&lt;/em&gt; por rendimiento.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pasos para solucionarlo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Opción 1: Evitar la actualización innecesaria (recomendada)
&lt;/h3&gt;

&lt;p&gt;No actualices el estado si no hay cambios reales. Usa una condición para verificar si realmente necesitas hacer el set:&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;useEffect&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;// Solo actualizar si el objeto no está vacío&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&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;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIngredients&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="nx"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Opción 2: Usar &lt;code&gt;useMemo&lt;/code&gt; para mantener la misma referencia
&lt;/h3&gt;

&lt;p&gt;Si necesitas mantener un objeto/array constante en memoria:&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;emptyIngredients&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&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;[]);&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&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;setIngredients&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;emptyIngredients&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;emptyIngredients&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Opción 3: Comparar contenido manualmente con &lt;code&gt;JSON.stringify&lt;/code&gt; (solo para estructuras simples)
&lt;/h3&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Solo para objetos planos sin funciones ni métodos&lt;/strong&gt;&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;useEffect&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;current&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;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ingredients&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;target&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;stringify&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;current&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIngredients&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="nx"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Opción 4: Usar &lt;code&gt;useReducer&lt;/code&gt; para lógica compleja
&lt;/h3&gt;

&lt;p&gt;Para estados complejos, &lt;code&gt;useReducer&lt;/code&gt; es más adecuado y evita este tipo de problemas:&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;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;items&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;reducer&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;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reset&lt;/span&gt;&lt;span class="dl"&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;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;items&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="nl"&gt;default&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;state&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;const&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;dispatch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&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;// Lógica que decide cuándo resetear&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;shouldReset&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;items&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reset&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;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bloque de código corregido (solución definitiva)
&lt;/h2&gt;

&lt;p&gt;La solución más limpia y performante para tu caso específico:&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;ingredients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIngredients&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="nf"&gt;useEffect&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;// Solo actualizar si hay algo que resetear&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&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;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIngredients&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// No incluir ingredients en las dependencias para evitar el bucle&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;h2&gt;
  
  
  Pro-tip
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nunca incluyas objetos/arrays directamente como dependencias&lt;/strong&gt; si vas a crear nuevos objetos en el &lt;code&gt;useEffect&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Usa &lt;code&gt;useMemo&lt;/code&gt; para mantener referencias estables cuando necesites comparar objetos&lt;/li&gt;
&lt;li&gt;Para arrays, considera usar &lt;code&gt;useMemo&lt;/code&gt; con &lt;code&gt;JSON.stringify&lt;/code&gt; o bibliotecas como &lt;code&gt;immer&lt;/code&gt; para manejo de estado inmutable&lt;/li&gt;
&lt;li&gt;Si el estado es complejo, &lt;code&gt;useReducer&lt;/code&gt; es casi siempre mejor que múltiples &lt;code&gt;useState&lt;/code&gt; con efectos interdependientes&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>debugging</category>
      <category>javascript</category>
      <category>react</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Cómo solucionar el error de permiso al ejecutar `pip.exe` en un entorno virtual de Python (Windows)</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Thu, 16 Jul 2026 10:52:05 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-el-error-de-permiso-al-ejecutar-pipexe-en-un-entorno-virtual-de-python-windows-dl0</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-el-error-de-permiso-al-ejecutar-pipexe-en-un-entorno-virtual-de-python-windows-dl0</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar el error de permiso al ejecutar &lt;code&gt;pip.exe&lt;/code&gt; en un entorno virtual de Python (Windows)
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Explicación técnica
&lt;/h2&gt;

&lt;p&gt;El problema ocurre porque el archivo &lt;code&gt;pip.exe&lt;/code&gt; en &lt;code&gt;venv/Scripts/&lt;/code&gt; es un &lt;em&gt;launcher&lt;/em&gt; empaquetado que contiene una ruta fija a &lt;code&gt;python.exe&lt;/code&gt; y un script &lt;code&gt;__main__.py&lt;/code&gt; incrustado. Cuando se crea el entorno virtual, este launcher se genera con la ruta absoluta al &lt;code&gt;python.exe&lt;/code&gt; que se usó para crearlo.&lt;/p&gt;

&lt;p&gt;Si después de crear el entorno virtual:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Se mueve el entorno (por ejemplo, al cambiar de disco, usuario o carpeta),&lt;/li&gt;
&lt;li&gt;Se reinstala Python en otra ubicación,&lt;/li&gt;
&lt;li&gt;O se usa una versión distinta de Python (especialmente si se instaló desde Microsoft Store, que usa rutas dinámicas como &lt;code&gt;C:\Users\&amp;lt;user&amp;gt;\AppData\Local\Microsoft\WindowsApps\python.exe&lt;/code&gt;),&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...entonces el launcher &lt;code&gt;pip.exe&lt;/code&gt; sigue apuntando a una ruta &lt;em&gt;obsoleta o inaccesible&lt;/em&gt;, causando el error &lt;strong&gt;"Access is denied"&lt;/strong&gt; al intentar ejecutarlo, incluso si los permisos del archivo son correctos.&lt;/p&gt;

&lt;p&gt;Este es un problema conocido en Windows con lanzadores empaquetados (como &lt;code&gt;pip.exe&lt;/code&gt;, &lt;code&gt;pythonw.exe&lt;/code&gt;, etc.) y es especialmente común con instalaciones de Python desde Microsoft Store, ya que usan redirecciones de alias (&lt;code&gt;python.exe&lt;/code&gt; → &lt;code&gt;WindowsApps\...&lt;/code&gt;) que se rompen al cambiar de contexto.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pasos para solucionarlo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ Paso 1: Verifica si el problema es el launcher (no los permisos)
&lt;/h3&gt;

&lt;p&gt;Ejecuta en CMD (¡no en bash!):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"C:\ruta\completa\al\venv\Scripts\pip.exe" -V
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si obtienes &lt;strong&gt;"Access is denied"&lt;/strong&gt;, el problema está en el launcher, no en permisos (como confirmó el usuario con &lt;code&gt;icacls&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Paso 2: Recrea el entorno virtual con la versión correcta de Python
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;No uses el &lt;code&gt;python.exe&lt;/code&gt; de Microsoft Store para crear entornos virtuales.&lt;/strong&gt; Usa siempre el instalador oficial de python.org (o el de tu distribución corporativa), y asegúrate de que esté en el &lt;code&gt;PATH&lt;/code&gt; &lt;em&gt;antes&lt;/em&gt; de &lt;code&gt;WindowsApps&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Desinstala Python de Microsoft Store (si no lo necesitas para otras apps).&lt;/li&gt;
&lt;li&gt;Descarga e instala Python 3.10.11 desde &lt;a href="https://www.python.org/downloads/release/python-31011/" rel="noopener noreferrer"&gt;python.org&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Verifica que el &lt;code&gt;python.exe&lt;/code&gt; correcto se use:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   where python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Debe mostrar algo como &lt;code&gt;C:\Python310\python.exe&lt;/code&gt;, &lt;strong&gt;no&lt;/strong&gt; &lt;code&gt;C:\Users\...\AppData\Local\Microsoft\WindowsApps\python.exe&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Elimina el entorno virtual actual:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   rmdir /s /q "C:\ruta\al\proyecto\venv"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Crea el entorno &lt;em&gt;desde cero&lt;/em&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   cd C:\ruta\al\proyecto
   python -m venv venv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✅ Paso 3: Verifica que &lt;code&gt;pip.exe&lt;/code&gt; funcione
&lt;/h3&gt;

&lt;p&gt;Activa el entorno y ejecuta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;venv\Scripts\activate
"C:\ruta\al\proyecto\venv\Scripts\pip.exe" -V
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Debería mostrar algo como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;pip 23.2.1 from C:\ruta\al\proyecto\venv\Lib\site-packages\pip (python 3.10)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✅ Paso 4: Usa &lt;code&gt;python -m pip&lt;/code&gt; como fallback (recomendado)
&lt;/h3&gt;

&lt;p&gt;Aunque el launcher funcione, es más robusto usar siempre:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python -m pip install -e .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto evita problemas con lanzadores corruptos o desactualizados, ya que usa directamente el &lt;code&gt;python.exe&lt;/code&gt; del entorno.&lt;/p&gt;




&lt;h2&gt;
  
  
  Bloque de código corregido (comandos finales)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:: Desinstala Python de Microsoft Store (opcional, pero recomendado)
:: Luego instala Python 3.10.11 desde python.org

:: Verifica el python correcto
where python

:: Elimina el entorno roto
rmdir /s /q "C:\ruta\al\proyecto\venv"

:: Crea el entorno con el python correcto
cd C:\ruta\al\proyecto
python -m venv venv

:: Activa y prueba
venv\Scripts\activate
"C:\ruta\al\proyecto\venv\Scripts\pip.exe" -V

:: Usa siempre este formato para evitar futuros problemas
python -m pip install -e .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Pro-tip: Evita este problema en el futuro
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nunca muevas o copies manualmente un entorno virtual.&lt;/strong&gt; Si necesitas moverlo, recrea el entorno.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evita Microsoft Store para desarrollo Python.&lt;/strong&gt; Usa instaladores &lt;code&gt;.exe&lt;/code&gt; de python.org o administradores como &lt;code&gt;pyenv-win&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Si usas múltiples versiones de Python&lt;/strong&gt;, usa &lt;code&gt;py -3.10 -m venv venv&lt;/code&gt; para garantizar la versión correcta.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guarda el hash del &lt;code&gt;python.exe&lt;/code&gt; original&lt;/strong&gt; en un archivo &lt;code&gt;venv/.python-version&lt;/code&gt; para detectar desincronizaciones rápidamente:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  certutil -hashfile "C:\ruta\al\venv\Scripts\python.exe" SHA256 &amp;gt; venv/.python-version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🔑 &lt;strong&gt;Clave&lt;/strong&gt;: El problema no es de permisos, es de &lt;em&gt;rutas rotas en lanzadores empaquetados&lt;/em&gt;. Recrear el entorno con el &lt;code&gt;python.exe&lt;/code&gt; correcto soluciona el 99% de los casos.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>debugging</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Cómo solucionar el bucle infinito en useEffect con objetos y arrays</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Wed, 15 Jul 2026 10:43:54 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-el-bucle-infinito-en-useeffect-con-objetos-y-arrays-1m92</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-el-bucle-infinito-en-useeffect-con-objetos-y-arrays-1m92</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar el bucle infinito en useEffect con objetos y arrays
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Explicación técnica
&lt;/h2&gt;

&lt;p&gt;El problema ocurre porque &lt;code&gt;useEffect&lt;/code&gt; compara las dependencias usando &lt;strong&gt;comparación superficial (shallow comparison)&lt;/strong&gt;, no profunda. Cuando pasas un objeto o array como dependencia (ej. &lt;code&gt;[obj]&lt;/code&gt;), React compara si la referencia en memoria es la misma, no si su contenido es idéntico.&lt;/p&gt;

&lt;p&gt;En tu caso:&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;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setObj&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="nf"&gt;useEffect&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;setObj&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt; &lt;span class="c1"&gt;// ¡Crea un NUEVO objeto en memoria!&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="c1"&gt;// obj anterior ≠ nuevo objeto → efecto se dispara infinitamente&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cada llamada a &lt;code&gt;setObj({})&lt;/code&gt; genera un objeto nuevo en memoria. Aunque su contenido es idéntico, su referencia es diferente, por lo que React detecta un "cambio" y vuelve a ejecutar el efecto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solución definitiva
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Opción 1: Evitar mutaciones innecesarias (recomendada)
&lt;/h3&gt;

&lt;p&gt;Solo actualiza el estado si realmente hay un cambio significativo:&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;useEffect&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;// Solo actualiza si el objeto no es el esperado&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&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;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIngredients&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="nx"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Opción 2: Usar comparación profunda con &lt;code&gt;useDeepCompareEffect&lt;/code&gt; (recomendada para casos complejos)
&lt;/h3&gt;

&lt;p&gt;Instala la librería &lt;a href="https://www.npmjs.com/package/use-deep-compare-effect" rel="noopener noreferrer"&gt;use-deep-compare-effect&lt;/a&gt;:&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;use-deep-compare-effect
&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;useDeepCompareEffect&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;use-deep-compare-effect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;useDeepCompareEffect&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;setIngredients&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;ingredients&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Opción 3: Normalizar el estado (recomendada para estado complejo)
&lt;/h3&gt;

&lt;p&gt;En lugar de guardar objetos completos, guarda solo los valores primitivos necesarios:&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="c1"&gt;// En lugar de: const [ingredients, setIngredients] = useState({});&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;ingredientCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIngredientCount&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ingredientCount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIngredientCount&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="c1"&gt;// Primitivo → comparación por valor&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;ingredientCount&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bloque de código corregido
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Versión más limpia y segura:&lt;/strong&gt;&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;ingredients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIngredients&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="nf"&gt;useEffect&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;// Evita el bucle infinito verificando si hay algo que limpiar&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&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;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIngredients&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="nx"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Para casos donde necesitas limpiar siempre (ej. reiniciar después de una operación):&lt;/strong&gt;&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;shouldReset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setShouldReset&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="nf"&gt;useEffect&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shouldReset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIngredients&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
    &lt;span class="nf"&gt;setShouldReset&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="c1"&gt;// Resetear bandera explícitamente&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;shouldReset&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pro-tip
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Nunca uses objetos/arrays literales como dependencias&lt;/strong&gt; si van a cambiar: &lt;code&gt;[obj]&lt;/code&gt; → &lt;code&gt;[obj.id, obj.version]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Para arrays&lt;/strong&gt;: compara longitudes o usa &lt;code&gt;JSON.stringify()&lt;/code&gt; solo en desarrollo (no en producción por rendimiento)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Patrón recomendado&lt;/strong&gt;: usa banderas booleanas para operaciones de "reset"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React 18+&lt;/strong&gt;: considera usar &lt;code&gt;useReducer&lt;/code&gt; para lógica de estado compleja con objetos&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Evita &lt;code&gt;useEffect(() =&amp;gt; {}, [])&lt;/code&gt; como solución general&lt;/strong&gt;: Esto elimina la lógica de actualización por completo y puede causar bugs de stale state. La solución debe abordar la raíz del problema: la comparación de referencias vs contenido.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>debugging</category>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Cómo solucionar el error \"Text content does not match server-rendered HTML\" en Next.js App Router</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Tue, 14 Jul 2026 10:39:59 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-el-error-text-content-does-not-match-server-rendered-html-en-nextjs-app-router-1e50</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-el-error-text-content-does-not-match-server-rendered-html-en-nextjs-app-router-1e50</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar el error "Text content does not match server-rendered HTML" en Next.js App Router
&lt;/h1&gt;

&lt;p&gt;Este error ocurre cuando el HTML generado en el servidor (SSR/SSG) no coincide con lo que React intenta renderizar en el navegador durante la hidratación. Es un problema crítico que rompe la experiencia de usuario y puede afectar el SEO.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Por qué ocurre?
&lt;/h2&gt;

&lt;p&gt;En Next.js App Router, el servidor genera HTML estático que luego se "hidrata" en el cliente. Si el árbol de React en el navegador difiere &lt;em&gt;en estructura o contenido&lt;/em&gt; del HTML inicial, React lanza este error. Las causas más comunes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uso de APIs del navegador (&lt;code&gt;window&lt;/code&gt;, &lt;code&gt;localStorage&lt;/code&gt;, &lt;code&gt;Date.now()&lt;/code&gt;) en el renderizado inicial.&lt;/li&gt;
&lt;li&gt;Lógica condicional basada en &lt;code&gt;typeof window !== 'undefined'&lt;/code&gt; dentro del render.&lt;/li&gt;
&lt;li&gt;Componentes con estado inicial diferente entre servidor y cliente (ej. &lt;code&gt;useState&lt;/code&gt; con valor no determinista).&lt;/li&gt;
&lt;li&gt;Metaetiquetas de detección automática en iOS (&lt;code&gt;format-detection&lt;/code&gt;) que inyectan enlaces &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; dinámicamente.&lt;/li&gt;
&lt;li&gt;Minificación automática de CDN (Cloudflare, Vercel Edge) que altera el HTML prerrendereado.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Solución definitiva (pasos verificados)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ Paso 1: Identifica la fuente del desajuste
&lt;/h3&gt;

&lt;p&gt;Busca en tu código:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Date()&lt;/code&gt;, &lt;code&gt;new Date()&lt;/code&gt;, &lt;code&gt;Math.random()&lt;/code&gt;, &lt;code&gt;window&lt;/code&gt;, &lt;code&gt;localStorage&lt;/code&gt;, &lt;code&gt;navigator&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;Uso de &lt;code&gt;useState&lt;/code&gt; con valores no deterministas (ej. &lt;code&gt;useState(() =&amp;gt; Math.random())&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Componentes que renderizan contenido diferente según el entorno sin protección&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🔍 &lt;strong&gt;Herramienta útil&lt;/strong&gt;: Usa &lt;code&gt;console.log('client')&lt;/code&gt; dentro de componentes para ver si se ejecutan en SSR (no aparecerá en logs del servidor).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  ✅ Paso 2: Aplica la solución según el caso
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Caso A: Contenido dinámico (fechas, IDs, tokens)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Solución recomendada&lt;/strong&gt;: &lt;code&gt;suppressHydrationWarning&lt;/code&gt; en el elemento específico.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Mal: desajuste directo&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Última actualización: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Bien: suprime advertencia en el elemento problemático&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;suppressHydrationWarning&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  Última actualización: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Importante&lt;/strong&gt;: Solo usa &lt;code&gt;suppressHydrationWarning&lt;/code&gt; en elementos &lt;em&gt;textuales&lt;/em&gt; y de bajo impacto visual. Nunca en contenedores estructurales.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h4&gt;
  
  
  Caso B: Lógica condicional basada en entorno
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Solución recomendada&lt;/strong&gt;: Usa &lt;code&gt;useEffect&lt;/code&gt; para diferir la lógica client-side.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&lt;/span&gt;&lt;span class="dl"&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;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&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="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ClientOnlyComponent&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;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cargando...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&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;// Solo se ejecuta en el cliente&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stored&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stored&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invitado&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="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;Hola, &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&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;blockquote&gt;
&lt;p&gt;✅ &lt;strong&gt;Ventaja&lt;/strong&gt;: El servidor renderiza &lt;code&gt;"Cargando..."&lt;/code&gt;, y el cliente lo actualiza sin desajuste.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h4&gt;
  
  
  Caso C: Componente totalmente client-side (ej. gráficos, canvas)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Solución recomendada&lt;/strong&gt;: Deshabilita SSR con &lt;code&gt;next/dynamic&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/Chart.tsx&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;dynamic&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;next/dynamic&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;Chart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Chart&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="na"&gt;ssr&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&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;div&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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Dashboard&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&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;Chart&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;div&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;✅ &lt;strong&gt;Ventaja&lt;/strong&gt;: El componente no se renderiza en el servidor → cero riesgo de desajuste.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  ✅ Paso 3: Solución global para iOS (frecuente en App Router)
&lt;/h3&gt;

&lt;p&gt;Agrega esta metaetiqueta en &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; de tu layout principal (&lt;code&gt;app/layout.tsx&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/layout.tsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;RootLayout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&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="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&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;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"es"&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;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="nt"&gt;meta&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"format-detection"&lt;/span&gt;
          &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"telephone=no, date=no, email=no, address=no"&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;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="nt"&gt;body&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;children&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;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="nt"&gt;html&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;📱 &lt;strong&gt;Por qué&lt;/strong&gt;: iOS inyecta automáticamente &lt;code&gt;&amp;lt;a href="tel:..."&amp;gt;&lt;/code&gt; en números de teléfono, rompiendo el HTML prerrendereado.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Pro-tip: Prevención definitiva
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Nunca uses APIs del navegador en el render top-level&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;   &lt;span class="c1"&gt;// ❌ Evitar&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;time&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;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&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;time&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;time&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;time&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Valida siempre estructuras HTML&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; no puede contener &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; no puede contener otro &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; ni &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;En entornos de producción&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Desactiva minificación automática de HTML en Cloudflare (o configura reglas para excluir &lt;code&gt;/app/**&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Usa &lt;code&gt;next.config.js&lt;/code&gt; para deshabilitar optimizaciones problemáticas:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// Solo si es estrictamente necesario&lt;/span&gt;
   &lt;span class="c1"&gt;// experimental: { optimizePackageImports: true },&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prueba en modo estricto&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   npm run dev &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--turbo&lt;/span&gt;
   &lt;span class="c"&gt;# o&lt;/span&gt;
   npm run build &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ¿Sigues teniendo el error?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Verifica extensiones del navegador&lt;/strong&gt;: Desactiva todas y prueba en modo incógnito.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revisa tu CDN/Edge&lt;/strong&gt;: Cloudflare, Fastly, o Vercel Edge Functions pueden alterar el HTML.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usa &lt;code&gt;console.log&lt;/code&gt; en el servidor&lt;/strong&gt;: Añade &lt;code&gt;console.log('Server render:', JSON.stringify(data))&lt;/code&gt; para comparar con el cliente.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🔥 &lt;strong&gt;Último recurso&lt;/strong&gt;: Usa &lt;code&gt;suppressHydrationWarning&lt;/code&gt; en el &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; o &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; como medida de último momento — &lt;strong&gt;solo si entiendes los riesgos&lt;/strong&gt; (pierdes validación de hidratación en toda la página).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Con esto, el error desaparecerá en &amp;lt;5 minutos. ¡A codear!&lt;/p&gt;

</description>
      <category>debugging</category>
      <category>nextjs</category>
      <category>react</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Cómo solucionar `docker run` con `Exited (1)` en Raspberry Pi</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Sun, 12 Jul 2026 10:21:26 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-docker-run-con-exited-1-en-raspberry-pi-2nee</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-docker-run-con-exited-1-en-raspberry-pi-2nee</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar &lt;code&gt;docker run&lt;/code&gt; con &lt;code&gt;Exited (1)&lt;/code&gt; en Raspberry Pi
&lt;/h1&gt;

&lt;h2&gt;
  
  
  ¿Por qué ocurre este error?
&lt;/h2&gt;

&lt;p&gt;El código de salida &lt;code&gt;1&lt;/code&gt; indica que el proceso principal del contenedor terminó con un error genérico. En Raspberry Pi, los casos más comunes son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Arquitectura incompatible&lt;/strong&gt;: La imagen fue construida para &lt;code&gt;amd64&lt;/code&gt; (x86_64), pero Raspberry Pi usa &lt;code&gt;armhf&lt;/code&gt; o &lt;code&gt;arm64&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Falta de binarios compatibles&lt;/strong&gt;: El &lt;code&gt;ENTRYPOINT&lt;/code&gt; o &lt;code&gt;CMD&lt;/code&gt; del contenedor intenta ejecutar un binario compilado para otra arquitectura.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Problemas de permisos o recursos&lt;/strong&gt;: Especialmente en entornos embebidos como Raspberry Pi, donde pueden faltar dispositivos (&lt;code&gt;/dev/*&lt;/code&gt;) o permisos de ejecución.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uso incorrecto de &lt;code&gt;--net = host&lt;/code&gt;&lt;/strong&gt;: El espacio de nombres de red &lt;code&gt;host&lt;/code&gt; requiere privilegios elevados y puede fallar si el contenedor no tiene &lt;code&gt;--privileged&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🔍 &lt;strong&gt;Clave diagnóstica&lt;/strong&gt;: El hecho de que funcione en una VM de Raspberry Pi (probablemente emulando x86_64 con QEMU) pero no en el hardware físico confirma que el problema es &lt;strong&gt;arquitectura&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Pasos para solucionarlo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Verifica la arquitectura del host y de la imagen
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Arquitectura del host (Raspberry Pi)&lt;/span&gt;
&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;

&lt;span class="c"&gt;# Arquitectura de la imagen&lt;/span&gt;
docker inspect &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{{.Architecture}}'&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si el host muestra &lt;code&gt;armv7l&lt;/code&gt; o &lt;code&gt;aarch64&lt;/code&gt;, pero la imagen muestra &lt;code&gt;amd64&lt;/code&gt;, &lt;strong&gt;la arquitectura no coincide&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Ejecuta el contenedor en primer plano para ver el error real
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Nota&lt;/strong&gt;: Quita &lt;code&gt;-d&lt;/code&gt; (background) y &lt;code&gt;-t&lt;/code&gt; (TTY) para ver los logs en tiempo real. Si el error es por arquitectura, verás algo como:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;standard_init_linux.go:211: exec user process caused: no such file or directory
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  3. Construye o descarga una imagen compatible con ARM
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Opción A: Usa imágenes oficiales multiarquitectura (recomendado)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ejemplo: imagen oficial de Python compatible con ARM&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; python:3.11-slim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Opción B: Construye la imagen en la Raspberry Pi
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clona o copia tu Dockerfile en la Pi&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; myimage &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Opción C: Usa QEMU para emular (solo para pruebas)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Instala soporte multiarquitectura&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;qemu-user-static

&lt;span class="c"&gt;# Registra el binario en Docker&lt;/span&gt;
docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--privileged&lt;/span&gt; multiarch/qemu-user-static &lt;span class="nt"&gt;--reset&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nb"&gt;yes&lt;/span&gt;

&lt;span class="c"&gt;# Ahora puedes ejecutar imágenes x86_64 (lento)&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  4. Corrige el comando &lt;code&gt;--net=host&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;El espacio de nombres &lt;code&gt;host&lt;/code&gt; &lt;strong&gt;no requiere espacios&lt;/strong&gt; en el argumento:&lt;/p&gt;

&lt;p&gt;❌ &lt;code&gt;--net = host&lt;/code&gt;&lt;br&gt;&lt;br&gt;
✅ &lt;code&gt;--net=host&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;El error de sintaxis puede causar que Docker interprete &lt;code&gt;=&lt;/code&gt; como parte del valor, fallando silenciosamente o lanzando un error no obvio.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h3&gt;
  
  
  5. Verifica permisos y dispositivos
&lt;/h3&gt;

&lt;p&gt;Si el contenedor necesita acceso a hardware (GPIO, I2C, etc.), añade:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--privileged&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; /dev:/dev &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;code&gt;--privileged&lt;/code&gt; es peligroso en producción. Usa &lt;code&gt;--cap-add=SYS_ADMIN&lt;/code&gt; o dispositivos específicos (&lt;code&gt;--device=/dev/i2c-1&lt;/code&gt;) si solo necesitas acceso limitado.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Bloque de código corregido
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Paso 1: Verifica arquitectura&lt;/span&gt;
docker inspect &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{{.Architecture}}'&lt;/span&gt; myimage

&lt;span class="c"&gt;# Paso 2: Ejecuta en primer plano para debug&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; myimage

&lt;span class="c"&gt;# Paso 3: Si falla por arquitectura, reconstruye o usa multiarch&lt;/span&gt;
&lt;span class="c"&gt;# Opción recomendada: construye localmente&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; myimage-arm &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Paso 4: Ejecuta con sintaxis correcta y permisos necesarios&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage-arm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Pro-tip: Automatiza la detección de arquitectura
&lt;/h2&gt;

&lt;p&gt;Crea un script de inicio rápido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nv"&gt;ARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ARCH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in
  &lt;/span&gt;armv7l&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;IMAGE_TAG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"arm32v7/myimage"&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
  aarch64&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;IMAGE_TAG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"arm64v8/myimage"&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
  &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Arquitectura no soportada: &lt;/span&gt;&lt;span class="nv"&gt;$ARCH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1 &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="k"&gt;esac&lt;/span&gt;

docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE_TAG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;✅ &lt;strong&gt;Resultado esperado&lt;/strong&gt;: El contenedor se inicia y permanece en ejecución (&lt;code&gt;docker ps&lt;/code&gt; muestra estado &lt;code&gt;Up&lt;/code&gt;). Si sigue fallando, revisa los logs con &lt;code&gt;docker logs &amp;lt;container_id&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>docker</category>
      <category>iot</category>
      <category>linux</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Cómo solucionar `docker run` con error `Exited (1)` en Raspberry Pi</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Sat, 11 Jul 2026 10:10:39 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-docker-run-con-error-exited-1-en-raspberry-pi-1akn</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-docker-run-con-error-exited-1-en-raspberry-pi-1akn</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar &lt;code&gt;docker run&lt;/code&gt; con error &lt;code&gt;Exited (1)&lt;/code&gt; en Raspberry Pi
&lt;/h1&gt;

&lt;h2&gt;
  
  
  ¿Por qué ocurre este error?
&lt;/h2&gt;

&lt;p&gt;El código de salida &lt;code&gt;1&lt;/code&gt; indica que el proceso principal del contenedor terminó con un error genérico. En Raspberry Pi, los casos más comunes son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Arquitectura incompatible&lt;/strong&gt;: La imagen fue construida para &lt;code&gt;amd64&lt;/code&gt; (x86_64), pero Raspberry Pi usa &lt;code&gt;armhf&lt;/code&gt; o &lt;code&gt;arm64&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Falta de binario de inicio&lt;/strong&gt;: La imagen no tiene un &lt;code&gt;ENTRYPOINT&lt;/code&gt; o &lt;code&gt;CMD&lt;/code&gt; válido, o el binario no existe/permisos incorrectos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faltan dependencias del sistema&lt;/strong&gt;: Librerías compartidas (&lt;code&gt;libc&lt;/code&gt;, &lt;code&gt;libstdc++&lt;/code&gt;, etc.) no compatibles con la versión de Raspbian.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Espacio en disco insuficiente&lt;/strong&gt;: Raspberry Pi suele tener particiones pequeñas en &lt;code&gt;/var/lib/docker&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Problemas con &lt;code&gt;--net=host&lt;/code&gt;&lt;/strong&gt;: En versiones antiguas de Docker en ARM, este modo puede fallar si el kernel no lo soporta adecuadamente.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🔍 &lt;strong&gt;Nota crítica&lt;/strong&gt;: El comando original tiene un error tipográfico: &lt;code&gt;--net = host&lt;/code&gt; (con espacios alrededor del &lt;code&gt;=&lt;/code&gt;) es inválido. Docker lo interpreta como &lt;code&gt;--net&lt;/code&gt; con valor &lt;code&gt;" = host"&lt;/code&gt;, lo que provoca fallos silenciosos o inesperados.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Pasos para solucionarlo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Corrige el comando y ejecuta en primer plano
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Elimina los espacios alrededor del '=' en --net=host&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-i&lt;/code&gt;: interactiva (mantiene stdin abierto)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-t&lt;/code&gt;: terminal (asigna pseudo-TTY)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--rm&lt;/code&gt;: elimina el contenedor al salir (limpieza automática)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;✅ Esto te mostrará el error real en tiempo real en lugar de ocultarlo con &lt;code&gt;-d&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  2. Verifica la arquitectura de la imagen
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker inspect myimage &lt;span class="nt"&gt;--format&lt;/span&gt; &lt;span class="s1"&gt;'{{.Architecture}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;En Raspberry Pi 3/4 (32-bit): debe ser &lt;code&gt;arm&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;En Raspberry Pi 4 (64-bit OS): debe ser &lt;code&gt;arm64&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Si muestra &lt;code&gt;amd64&lt;/code&gt;, la imagen es incompatible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solución: reconstruir para ARM
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Opción A: Construir localmente en la Pi&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; myimage &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Opción B: Usar multi-arch con buildx&lt;/span&gt;
docker buildx build &lt;span class="nt"&gt;--platform&lt;/span&gt; linux/arm/v7 &lt;span class="nt"&gt;-t&lt;/span&gt; myimage &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3. Verifica espacio en disco y sistema de archivos
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;df&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt; /var/lib/docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En Raspberry Pi, &lt;code&gt;/var/lib/docker&lt;/code&gt; suele estar en la partición raíz (&lt;code&gt;/&lt;/code&gt;), que por defecto es pequeña. Si está &amp;gt;90% usado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Limpieza agresiva (cuidado: borra contenedores/imagenes no usados)&lt;/span&gt;
docker system prune &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;--volumes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  4. Prueba sin &lt;code&gt;--net=host&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; myimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si funciona sin &lt;code&gt;--net=host&lt;/code&gt;, el problema está en la configuración de red del host. Verifica:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Versión de Docker (&lt;code&gt;docker --version&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Kernel (&lt;code&gt;uname -r&lt;/code&gt;) → debe ser ≥ 4.9 para soporte ARM completo&lt;/li&gt;
&lt;li&gt;Si usas Raspbian Lite, asegúrate de tener &lt;code&gt;iptables&lt;/code&gt; instalado.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  5. Verifica el &lt;code&gt;ENTRYPOINT&lt;/code&gt;/&lt;code&gt;CMD&lt;/code&gt; de la imagen
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker inspect myimage &lt;span class="nt"&gt;--format&lt;/span&gt; &lt;span class="s1"&gt;'{{.Config.Entrypoint}} {{.Config.Cmd}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si ambos son &lt;code&gt;null&lt;/code&gt;, el contenedor no tiene nada que ejecutar → sale con &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solución: especifica manualmente el comando
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; myimage /bin/sh
&lt;span class="c"&gt;# o&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; myimage /your/app/binary
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Bloque de código corregido (ejemplo funcional)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Limpieza inicial&lt;/span&gt;
docker system prune &lt;span class="nt"&gt;-af&lt;/span&gt;

&lt;span class="c"&gt;# 2. Verifica arquitectura&lt;/span&gt;
docker inspect myimage &lt;span class="nt"&gt;--format&lt;/span&gt; &lt;span class="s1"&gt;'{{.Architecture}}'&lt;/span&gt;

&lt;span class="c"&gt;# 3. Ejecuta en primer plano (sin --net=host para aislar el problema)&lt;/span&gt;
docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; myimage /bin/sh

&lt;span class="c"&gt;# 4. Si funciona, reintenta con red host (solo si es estrictamente necesario)&lt;/span&gt;
docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; myimage /bin/sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Pro-tip: Diagnóstico rápido con &lt;code&gt;strace&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Si el binario del contenedor falla silenciosamente, inyecta &lt;code&gt;strace&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--entrypoint&lt;/span&gt; /usr/bin/strace myimage &lt;span class="nt"&gt;-f&lt;/span&gt; /your/app/binary
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ Requiere que &lt;code&gt;strace&lt;/code&gt; esté incluido en la imagen. Si no, reconstruye la imagen añadiéndolo (&lt;code&gt;RUN apt-get install -y strace&lt;/code&gt;).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;strong&gt;Resultado esperado&lt;/strong&gt;: El contenedor se ejecutará sin &lt;code&gt;Exited (1)&lt;/code&gt;, o verás el error real en consola para actuar en consecuencia.&lt;/p&gt;

</description>
      <category>debugging</category>
      <category>docker</category>
      <category>iot</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Cómo solucionar el bucle infinito en `useEffect` con objetos y arrays</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Fri, 10 Jul 2026 11:45:22 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-el-bucle-infinito-en-useeffect-con-objetos-y-arrays-1h11</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-el-bucle-infinito-en-useeffect-con-objetos-y-arrays-1h11</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar el bucle infinito en &lt;code&gt;useEffect&lt;/code&gt; con objetos y arrays
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Explicación técnica
&lt;/h2&gt;

&lt;p&gt;El problema ocurre porque &lt;code&gt;useEffect&lt;/code&gt; compara los valores de las dependencias usando &lt;strong&gt;comparación de referencia (&lt;code&gt;===&lt;/code&gt;)&lt;/strong&gt;, no por contenido (shallow comparison). Cuando usas &lt;code&gt;useState({})&lt;/code&gt;, cada llamada a &lt;code&gt;setObj({})&lt;/code&gt; crea un &lt;strong&gt;nuevo objeto en memoria&lt;/strong&gt;, aunque tenga el mismo contenido. Por lo tanto:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;{} === {}&lt;/code&gt; → &lt;code&gt;false&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[1,2] === [1,2]&lt;/code&gt; → &lt;code&gt;false&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En tu caso:&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;ingredients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIngredients&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="nf"&gt;useEffect&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;setIngredients&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt; &lt;span class="c1"&gt;// ← ¡Crea un nuevo objeto!&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// ← Siempre es una referencia distinta → loop infinito&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;React detecta que la referencia cambia y vuelve a ejecutar el efecto, que a su vez vuelve a cambiar la referencia, creando un bucle infinito.&lt;/p&gt;




&lt;h2&gt;
  
  
  Solución definitiva (3 enfoques)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ Opción 1: Evitar la actualización innecesaria (recomendada)
&lt;/h3&gt;

&lt;p&gt;Si no necesitas actualizar el estado (como en tu ejemplo donde pones &lt;code&gt;{}&lt;/code&gt; en &lt;code&gt;{}&lt;/code&gt;), &lt;strong&gt;no llames al setter&lt;/strong&gt;:&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;useEffect&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;// Si el estado ya es {}, no necesitas hacer nada&lt;/span&gt;
  &lt;span class="c1"&gt;// Solo ejecuta lógica si hay algo que hacer&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt; &lt;span class="c1"&gt;// Dependencia vacía: solo corre una vez al montar&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✅ Opción 2: Comparación por contenido con &lt;code&gt;useDeepCompareEffect&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Crea un hook personalizado que compare por profundidad (deep comparison):&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRef&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="s1"&gt;react&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;useDeepCompareEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dependencies&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;previousDeps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dependencies&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;changedDeps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;previousDeps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&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;changedDeps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;previousDeps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dependencies&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;// Uso:&lt;/span&gt;
&lt;span class="nf"&gt;useDeepCompareEffect&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;setIngredients&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;ingredients&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Nota&lt;/strong&gt;: Usa librerías como &lt;a href="https://www.npmjs.com/package/use-deep-compare-effect" rel="noopener noreferrer"&gt;&lt;code&gt;use-deep-compare-effect&lt;/code&gt;&lt;/a&gt; en producción para evitar bugs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  ✅ Opción 3: Normalizar el estado y usar valores primitivos
&lt;/h3&gt;

&lt;p&gt;Convierte objetos/array en valores primitivos para comparación:&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;ingredients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIngredients&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ingredientsCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIngredientsCount&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&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;// Solo actualiza si el conteo cambia&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;ingredients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;ingredientsCount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIngredientsCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Tu lógica aquí&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;ingredientsCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Bloque de código corregido (ejemplo práctico)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Antes (bucle infinito):&lt;/strong&gt;&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;ingredients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIngredients&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="nf"&gt;useEffect&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;setIngredients&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt; &lt;span class="c1"&gt;// ← ¡Causa loop!&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Después (solución limpia):&lt;/strong&gt;&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;ingredients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIngredients&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="nf"&gt;useEffect&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;// Solo ejecutar si hay lógica real que necesite ejecutarse&lt;/span&gt;
  &lt;span class="c1"&gt;// Si solo quieres inicializar, usa una bandera o dependencia vacía&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt; &lt;span class="c1"&gt;// Dependencia vacía: ejecuta una vez al montar&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;O si necesitas resetear bajo condiciones específicas:&lt;/strong&gt;&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;ingredients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIngredients&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;resetTrigger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setResetTrigger&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="nf"&gt;useEffect&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resetTrigger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setIngredients&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
    &lt;span class="nf"&gt;setResetTrigger&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="c1"&gt;// Resetear la bandera&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;resetTrigger&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Pro-tip: Regla de oro para hooks con objetos/array
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nunca uses objetos/array como dependencias directas si vas a reasignarlos dentro del &lt;code&gt;useEffect&lt;/code&gt;.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
En su lugar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usa valores primitivos (IDs, longitudes, timestamps)&lt;/li&gt;
&lt;li&gt;Implementa comparación profunda con librerías probadas&lt;/li&gt;
&lt;li&gt;Reconsidera si realmente necesitas actualizar el estado (¿ya tiene el valor que quieres asignar?)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Bonus:&lt;/strong&gt; Si usas &lt;code&gt;immer&lt;/code&gt; o &lt;code&gt;useImmer&lt;/code&gt;, puedes evitar este problema con inmutabilidad controlada.&lt;/p&gt;

</description>
      <category>debugging</category>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
