<StrictMode> te permite encontrar errores comunes en los componentes al comienzo del desarrollo.

<StrictMode>
<App />
</StrictMode>

Referencia

<StrictMode>

Usa StrictMode para habilitar comportamientos de compilación y advertencias adicionales (Modo Estricto) dentro del árbol de componentes que se encuentra dentro:

import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';

const root = createRoot(document.getElementById('root'));
root.render(
<StrictMode>
<App />
</StrictMode>
);

Ver más ejemplos abajo.

El Modo Estricto habilita los siguientes comportamientos solo en desarrollo:

Props

StrictMode, no acepta props.

Advertencias

  • No hay forma de excluirse del Modo Estricto dentro de un árbol envuelto en <StrictMode>. Esto te asegura de que se comprueban todos los componentes dentro de <StrictMode>. Si dos equipos que trabajan en un producto no están de acuerdo sobre si le resultan valiosas estas comprobaciones, necesitarían o bien llegar a un consenso o bien mover <StrictMode> abajo en el árbol.

Uso

Habilitar el Modo Estricto para toda la aplicación

El Modo Estricto, habilita chequeos adicionales solo en desarrollo para el todo el árbol de componentes dentro del componente <StrictMode>. Estos chequeos ayudan a encontrar errores comunes en tus componentes al principio del proceso de desarrollo.

Para habilitar el Modo Estricto en toda tu aplicación, envuelve tu componente raíz con <StrictMode> cuando lo renderices:

import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';

const root = createRoot(document.getElementById('root'));
root.render(
<StrictMode>
<App />
</StrictMode>
);

Nuestra recomendación es que envuelvas toda tu aplicación en Modo Estricto, especialmente para aplicaciones recientemente creadas. Si usas un framework que hace la llamada a createRoot por ti, comprueba su documentación para saber como habilitar el Modo Estricto.

A pesar de que las comprobaciones del Modo Estricta solo se ejecutan en desarrollo, te ayudan a encontrar errores que ya existen en tu código, pero que puede ser difícil reproducirlos de forma confiable en producción. El Modo Estricto te permite corregir errores antes que tus usuarios los reporten.

Nota

El Modo Estricto habilita los siguientes chequeos en desarrollo:

Todos estos chequeos es hacen solo en desarrollo y no afectan la compilación de producción.


Habilitar el Modo Estricto para una parte de la aplicación

También puedes habilitar el Modo Estricto para cualquier parte de tu aplicación:

import { StrictMode } from 'react';

function App() {
return (
<>
<Header />
<StrictMode>
<main>
<Sidebar />
<Content />
</main>
</StrictMode>
<Footer />
</>
);
}

En este ejemplo, el chequeo de Strict Mode no se ejecutarán en los componentes Header y Footer. Sin embargo, sí se ejecutarán en Sidebar y Content al igual que todos los componentes dentro de estos, sin importar la profundidad.


Solución de errores encontrados por renderizado doble en desarrollo

React asume que cada componente que escribes es una función pura. Esto significa que los componentes de React que escribes deben siempre devolver el mismo JSX dadas las mismas entradas (props, estado y contexto).

Los componentes que rompen esta regla se comportan impredeciblemente y causan errores. Para ayudarte a encontrar código impuro accidental, el Modo Estricto llama algunas de tus funciones (solo las que deberían ser puras) dos veces en desarrollo. Esto incluye:

Si una función es pura, ejecutarla dos veces no cambia su comportamiento porque una función pura produce el mismo resultado cada vez. Sin embargo, si una función es impura (por ejemplo, si muta los datos que recibe), ejecutarla dos veces tiende a ser perceptible (¡eso es lo que la hace impura!) Esto te ayuda a detectar y corregir el error antes.

Aquí hay un ejemplo para ilustrar como el renderizado doble en el Modo Estricto te ayuda a encontrar errores antes.

Este componente StoryTray toma un array de stories y añade un último artículo «Create Story» al final:

export default function StoryTray({ stories }) {
  const items = stories;
  items.push({ id: 'create', label: 'Create Story' });
  return (
    <ul>
      {items.map(story => (
        <li key={story.id}>
          {story.label}
        </li>
      ))}
    </ul>
  );
}

Hay un error en el código arriba. Sin embargo, puede pasar desapercibido con facilidad porque la salida inicial parece correcta.

Este error será más perceptible si el componente StoryTray se vuelve a renderizar múltiples veces. Por ejemplo, hagamos que StoryTray se vuelva a renderizar con un diferente color de fondo cada vez que el puntero pase sobre el componente:

import { useState } from 'react';

export default function StoryTray({ stories }) {
  const [isHover, setIsHover] = useState(false);
  const items = stories;
  items.push({ id: 'create', label: 'Create Story' });
  return (
    <ul
      onPointerEnter={() => setIsHover(true)}
      onPointerLeave={() => setIsHover(false)}
      style={{
        backgroundColor: isHover ? '#ddd' : '#fff'
      }}
    >
      {items.map(story => (
        <li key={story.id}>
          {story.label}
        </li>
      ))}
    </ul>
  );
}

Date cuenta como cada momento que el puntero pasa por encima del componente StoryTray, «Create Story» se añade a la lista nuevamente. La intención del código fue añadirla una vez al final. Pero StoryTray, directamente modifica el array stories de las props. Cada momento que StoryTray se renderiza, añade «Create Story» de nuevo al final del mismo array. En otras palabras, StoryTray no es una función pura, ejecutándola múltiples veces produce diferente resultados.

Para arreglar este problema, puedes hacer una copia del array y modificar la copia en vez de la original:

export default function StoryTray({ stories }) {
const items = stories.slice(); // Clone the array
// ✅ Good: Pushing into a new array
items.push({ id: 'create', label: 'Create Story' });

Esto haría la función StoryTray pura. Cada vez que es llamada, solo modificaría una nueva copia del array y no afectaría cualquier objeto o variable externo. Esto soluciona el error, pero tuviste que hacer que el componente se vuelva a renderizar más a menudo antes que se convirtiera obvio que algo está mal con su comportamiento.

En el ejemplo original, el error no fue obvio. Ahora vamos a envolver el código original (con errores) en <StrictMode>

export default function StoryTray({ stories }) {
  const items = stories;
  items.push({ id: 'create', label: 'Create Story' });
  return (
    <ul>
      {items.map(story => (
        <li key={story.id}>
          {story.label}
        </li>
      ))}
    </ul>
  );
}

El Modo Estricto siempre llama a tu función de renderizado dos veces, por lo que puedes ver el error de inmediato («Create Story», aparece dos veces). Esto permite darte cuenta de este tipo de errores al principio en el proceso. Cuando corriges el componente para renderizarse en Modo Estricto, también corriges futuros posibles errores en producción como la funcionalidad hover (pasar por encima el puntero) de antes:

import { useState } from 'react';

export default function StoryTray({ stories }) {
  const [isHover, setIsHover] = useState(false);
  const items = stories.slice(); // Clone the array
  items.push({ id: 'create', label: 'Create Story' });
  return (
    <ul
      onPointerEnter={() => setIsHover(true)}
      onPointerLeave={() => setIsHover(false)}
      style={{
        backgroundColor: isHover ? '#ddd' : '#fff'
      }}
    >
      {items.map(story => (
        <li key={story.id}>
          {story.label}
        </li>
      ))}
    </ul>
  );
}

Sin Modo Estricto, era fácil saltarse el error hasta que agregaste más rerenderizados. El Modo Estricto hizo aparecer el mismo error de inmediato. El Modo Estricto te ayuda a encontrar errores antes de que se los subas a tu equipo y a tus usuarios.

Lee más sobre mantener componentes puros.

Nota

Si tienes instaladas las Herramientas de Desarrollo de React, cualquier llamada a console.log durante la segunda llamada al renderizado va a aparecer levemente atenuada. Las Herramientas de Desarrollo de React también ofrecen una configuración (desactivada por defecto) para suprimirlas completamente.


Arreglar errores detectados al volver ejecutar Efectos en desarrollo

El Modo Estricto puede también ayudar a encontrar errores en los Efectos.

Cada Efecto tiene algún código de configuración y podría tener algún código de limpieza. Normalmente, React llama al código de configuración cuando el componente se monta (se añadió a la pantalla) y llama a la limpieza cuando el componente se desmonta (se eliminó de la pantalla). React entonces llama a la limpieza y configuración de nuevo si sus dependencias cambiaron desde el último renderizado.

Cuando Strict Mode está activo, React también ejecutará un ciclo extra de configuración+limpieza en desarrollo por cada Efecto. Esto podría sorprender, pero ayuda a revelar errores sutiles que son difíciles de detectar manualmente.

Aquí tienes un ejemplo para ilustrarte cómo volver a renderizar Efectos en Modo Estricto ayuda a encontrar errores al principio.

Considera este ejemplo que conecta un componente a un chat:

import { useState, useEffect } from 'react';
import { createConnection } from './chat.js';

const serverUrl = 'https://localhost:1234';
const roomId = 'general';

export default function ChatRoom() {
  useEffect(() => {
    const connection = createConnection(serverUrl, roomId);
    connection.connect();
  }, []);
  return <h1>Welcome to the {roomId} room!</h1>;
}

Hay un problema con este código pero podría no quedar claro inmediatamente.

Para hacer este problema más obvio, implementemos una funcionalidad. En el siguiente ejemplo, roomId no está codificado de forma fija. En cambio, el usuario puede seleccionar el roomId al que quiere conectarse desde un dropdown. Haz clic en «Open chat» y luego selecciona diferentes salas de chat una por una. Mantén la cuenta del número de conexiones activas en la consola:

import { useState, useEffect } from 'react';
import { createConnection } from './chat.js';

const serverUrl = 'https://localhost:1234';

function ChatRoom({ roomId }) {
  useEffect(() => {
    const connection = createConnection(serverUrl, roomId);
    connection.connect();
  }, [roomId]);

  return <h1>Welcome to the {roomId} room!</h1>;
}

export default function App() {
  const [roomId, setRoomId] = useState('general');
  const [show, setShow] = useState(false);
  return (
    <>
      <label>
        Choose the chat room:{' '}
        <select
          value={roomId}
          onChange={e => setRoomId(e.target.value)}
        >
          <option value="general">general</option>
          <option value="travel">travel</option>
          <option value="music">music</option>
        </select>
      </label>
      <button onClick={() => setShow(!show)}>
        {show ? 'Close chat' : 'Open chat'}
      </button>
      {show && <hr />}
      {show && <ChatRoom roomId={roomId} />}
    </>
  );
}

Vas a darte cuenta de que el número de conexiones abiertas siempre se mantiene creciendo. En una aplicación real, esto causaría problemas de rendimiento y de red. El problema es que a tu Efecto le falta una función de limpieza:

useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => connection.disconnect();
}, [roomId]);

Ahora que tu Efecto “hace una limpieza” al concluir y destruye las conexiones obsoletas, la fuga está resuelta. Sin embargo, date cuenta de que el problema no se hizo visible hasta que añadiste más funcionaliades (el cuadro de selección).

En el ejemplo original, el error no era obvio. Ahora envolvamos el código original (con errores) en <StrictMode>:

import { useState, useEffect } from 'react';
import { createConnection } from './chat.js';

const serverUrl = 'https://localhost:1234';
const roomId = 'general';

export default function ChatRoom() {
  useEffect(() => {
    const connection = createConnection(serverUrl, roomId);
    connection.connect();
  }, []);
  return <h1>Welcome to the {roomId} room!</h1>;
}

Con Modo Estricto, ves inmediatamente que hay un problema (el número de conexiones activas salta a 2). El Modo Estricto ejecuta un ciclo extra de configuración+limpieza por cada Efecto. Este Efecto no tiene lógica de limpieza, por lo que crea una conexión extra, pero no la destruye. Esto es una pista de que te falta una función de limpieza.

El Modo Estricto te permite notar este tipo de errores al principio del proceso. Cuando corriges tu Efecto al añadir una función de limpieza en Modo Estricto, también corriges varios posibles futuros errores en producción como el cuadro de selección anterior:

import { useState, useEffect } from 'react';
import { createConnection } from './chat.js';

const serverUrl = 'https://localhost:1234';

function ChatRoom({ roomId }) {
  useEffect(() => {
    const connection = createConnection(serverUrl, roomId);
    connection.connect();
    return () => connection.disconnect();
  }, [roomId]);

  return <h1>Welcome to the {roomId} room!</h1>;
}

export default function App() {
  const [roomId, setRoomId] = useState('general');
  const [show, setShow] = useState(false);
  return (
    <>
      <label>
        Choose the chat room:{' '}
        <select
          value={roomId}
          onChange={e => setRoomId(e.target.value)}
        >
          <option value="general">general</option>
          <option value="travel">travel</option>
          <option value="music">music</option>
        </select>
      </label>
      <button onClick={() => setShow(!show)}>
        {show ? 'Close chat' : 'Open chat'}
      </button>
      {show && <hr />}
      {show && <ChatRoom roomId={roomId} />}
    </>
  );
}

Date cuenta de como la cuenta de conexiones activas en la consola ya no sigue creciendo.

Sin Modo Estricto, es fácil pasar por alto que tu Efecto necesita limpieza. Al ejecutar configuración → limpieza → configuración en vez de configuración para tu Efecto en desarrollo, el Modo Estricto hizo que la lógica de limpieza faltante fuera más notable.

Lee más sobre la implementación de la limpieza de los Efectos.


Arreglar advertencias de código obsoleto habilitadas en el Modo Estricto

React advierte si algún componente en cualquier lugar dentro de un árbol <StrictMode> usa una de estas API obsoletas:

Estas API son usadas principalmente en los componentes de clase más antiguos, por lo que no es común que aparezcan en aplicaciones modernas.