Tema representativo de entrevista

Entrevista de Frontend: ¿Cómo controlan las keys de React la preservación del estado y el remontaje?

FrontendIntermedio
Equipo editorial de Offer.ccPublicado Actualizado

Pregunta

Una página de React tiene una lista editable en la que los usuarios pueden ordenar, filtrar e insertar elementos. Cada fila mantiene un borrador local y un estado expandido. La página también alterna entre formularios de detalle para diferentes usuarios. Explica cómo afectan las keys a la identidad de los componentes y a la preservación del estado, por qué los índices de arreglos o los valores aleatorios causan errores y cuándo cambiar una key es la forma correcta de remontar un subárbol.

Pregunta y escenario aplicable

Una página de administración renderiza una lista de usuarios editable. Cada Row posee un borrador de entrada no enviado y un estado expandido. Los usuarios pueden insertar un registro al principio, eliminar un registro intermedio, ordenar y filtrar. Un formulario de detalle junto a la lista debe limpiar el estado local del usuario anterior cada vez que userId cambie.

Explica:

  1. Cómo decide React si un componente es el mismo componente entre renders adyacentes.
  2. Por qué key={index} puede mover borradores o el estado expandido a otro registro.
  3. Por qué key={Math.random()} remonta repetidamente los componentes.
  4. Cuándo un ID de dominio estable debe preservar el estado y cuándo cambiar una key debe restablecer un subárbol.
  5. Cómo verificar el comportamiento en inserciones, eliminaciones, ordenamientos, filtrados y cambios de entidad.

El material para entrevistas de React publicado en marzo y mayo de 2026 incluye directamente keys, keys de índice, reconciliación y remontaje. Aunque la consigna parece una simple sintaxis de listas, evalúa si un candidato puede modelar qué entidad lógica posee el estado y expresar ese modelo a través de los límites de los componentes y las pruebas.

Esta es una pregunta de frontend porque su competencia central radica en la identidad de los componentes de React, el tiempo de vida del estado y la reutilización del DOM.

Qué está evaluando el entrevistador

En primer lugar, el candidato debe saber que el estado no se adjunta automáticamente a una etiqueta JSX o a un objeto de dominio. React asocia el estado con una posición en el árbol de renderizado. Dentro de un mismo padre, el tipo de elemento y la key ayudan a determinar si los hijos anteriores y nuevos representan la misma identidad.

En segundo lugar, el candidato debe distinguir un re-render de un remontaje. Nuevas props o una actualización del padre pueden volver a renderizar la misma identidad mientras se preserva su estado local. Un cambio en el tipo de componente o en la key crea una nueva identidad, destruye el estado local del subárbol anterior y puede recrear su DOM.

En tercer lugar, el candidato debe derivar las keys a partir de la identidad de dominio. Un ID de base de datos o un UUID generado y almacenado cuando se crea un registro usualmente significa "este sigue siendo el mismo registro". Una posición de arreglo, una marca de tiempo actual o un valor aleatorio producido durante el renderizado no lo hacen.

En cuarto lugar, una respuesta sólida no convierte "nunca cambies una key" en una regla absoluta. Cuando un formulario de detalle cambia del usuario A al usuario B, los formularios pueden representar diferentes entidades de dominio. key={userId} en el límite correcto puede restablecer el subárbol completo del formulario de manera más confiable que limpiar variables de estado individuales en Effects.

Por último, el candidato debe mencionar el costo de remontar: el foco, la posición de desplazamiento (scroll), las entradas no enviadas y el estado de los descendientes se pueden perder por completo. Si el producto necesita restaurar un borrador cuando se vuelve a seleccionar una entidad, eleva el borrador (lift state), almacénalo por entidad o persístelo externamente en lugar de depender del estado local en un subárbol eliminado.

Preguntas de aclaración antes de responder

  • ¿Se pueden insertar, eliminar, ordenar o filtrar elementos en la lista? Una vez que la pertenencia o el orden pueden cambiar, un índice de arreglo no identifica

de forma estable una entidad de dominio.

  • ¿Cada fila posee estado de React o del DOM del navegador? Los inputs, el estado de expansión, las animaciones y los campos no controlados exponen rápidamente

una reutilización incorrecta.

  • ¿Los datos tienen un ID estable y único entre sus hermanos? Las keys necesitan ser únicas entre elementos hermanos, no globalmente únicas.
  • ¿Un cambio de entidad debe descartar o restaurar su borrador? Descartarlo encaja con un cambio de key; restaurarlo requiere una capa de

estado de mayor duración.

  • ¿Debe restablecerse todo el subárbol o solo un campo? Usa una key para un restablecimiento completo de la identidad; prefiere estado controlado o una

actualización explícita de datos para un ajuste parcial.

  • ¿Cuándo se genera el ID? Un registro local puede recibir un UUID cuando se crea y conservarlo. No generes uno nuevo en

cada renderizado.

Estructura de respuesta de 30 segundos

"React asocia el estado con posiciones en el árbol de renderizado. Bajo el mismo padre, el tipo de componente y la key ayudan a React a determinar si los nodos antiguos y nuevos tienen la misma identidad. Una key estable permite que el estado de la fila siga a un registro de dominio incluso cuando se mueve. Con un índice de arreglo, la inserción o el ordenamiento pueden colocar un registro diferente en la misma posición, por lo que un borrador local puede moverse a la fila incorrecta. Una key aleatoria nunca coincide con el renderizado anterior, por lo que React recrea repetidamente el componente y el DOM.

Las listas deben usar un ID estable proveniente de los datos. Si al pasar del formulario de detalle del usuario A al del usuario B se debe limpiar todo el estado local, colocaría key={userId} en el límite del subárbol del formulario para indicar que se trata de una nueva entidad. Si el borrador de cada usuario debe persistir, elevaría los borradores y los almacenaría por userId mientras mantengo el límite de identidad. Verificaría inserciones, eliminaciones, reordenamientos, filtrados, re-renders con el mismo ID y cambios a IDs diferentes para demostrar que el estado sigue a la entidad prevista."

Análisis detallado paso a paso

Paso 1: Construir un modelo de identidad de componentes.

Un modelo útil para entrevistas es:

Relación entre el render antiguo y el nuevoResultado típico
Mismo padre, mismo tipo de componente, misma keyPreserva el estado local de esa identidad; el componente puede volver a renderizarse
Mismo padre, mismo tipo, diferente keyElimina la identidad anterior, monta una nueva y restablece el estado del subárbol
Misma posición, diferente tipo de componenteReemplaza el subárbol anterior y restablece el estado
Lista sin una key explícitaRecurre a la coincidencia posicional, lo cual es inseguro para listas dinámicas

key no es una prop ordinaria que se entregue al componente. Es una pista para React. Si Row también necesita el ID de dominio, pasa una prop separada como rowId={item.id}.

Una key también define la identidad únicamente dentro de su padre actual. Dos listas separadas pueden contener ambas key="user-42", mientras que los elementos hermanos dentro de una misma lista no deben tener keys duplicadas.

Paso 2: Reproducir el error de key por índice con una lista editable.

Implementación incorrecta:

tsx
function UserList({ users }: { users: User[] }) {
  return users.map((user, index) => (
    <EditableRow key={index} user={user} />
  ))
}

Supongamos que el orden inicial es [Alice, Bob]. El EditableRow en el índice 0 almacena el borrador de Alice. Inserta a Zoe al principio, produciendo [Zoe, Alice, Bob]. React puede hacer coincidir la fila antigua con key 0 con el nuevo elemento en el índice 0, por lo que el estado que pertenecía a Alice puede aparecer en la fila de Zoe. El estado en la key 1 puede de manera similar moverse de Bob a Alice.

El problema no es que un índice sea un número. El índice identifica una posición (slot) mientras que el producto necesita identificar a un usuario. La eliminación, el ordenamiento y el filtrado cambian la correspondencia entre posiciones y entidades.

Implementación correcta:

tsx
function UserList({ users }: { users: User[] }) {
  return users.map((user) => (
    <EditableRow key={user.id} rowId={user.id} user={user} />
  ))
}

Después de insertar a Zoe, Alice sigue teniendo el ID de Alice. Puede moverse del índice 0 al índice 1, y React puede continuar haciendo coincidir el estado del componente de Alice con Alice.

Si un registro devuelve varios nodos hermanos, la sintaxis corta de Fragment no puede recibir una key. Usa un Fragment explícito:

tsx
import { Fragment } from 'react'

users.map((user) => (
  <Fragment key={user.id}>
    <UserHeading user={user} />
    <EditableRow user={user} />
  </Fragment>
))

Paso 3: Elegir una key estable en lugar de fabricar una durante el render.

Un orden de preferencia práctico es:

  1. Un ID de registro estable del backend o base de datos.
  2. Un identificador único ya adjunto a los datos y sin cambios a lo largo de su ciclo de vida en el dominio.
  3. Para un registro nuevo puramente local, un UUID generado en el evento de creación del registro y persistido junto a él.
  4. Una key compuesta solo cuando sus campos formen verdaderamente una identidad de dominio inmutable y única entre hermanos.

Lo siguiente crea una nueva identidad en cada render:

tsx
<EditableRow key={Math.random()} user={user} />

Esto no es un re-render ordinario. React elimina la fila antigua y monta una nueva. El estado local y la entrada del usuario se pierden, y el DOM se vuelve a crear. Date.now() o llamar a crypto.randomUUID() durante el render tiene el mismo problema. Un UUID funciona bien cuando se genera una vez durante la creación del elemento y se almacena, no cuando se genera mientras se renderiza el elemento.

Un índice de arreglo es aceptable solo bajo un contrato estricto: la pertenencia y el orden permanecen fijos durante toda la vida útil de la lista, no hay inserción, eliminación, filtrado ni reordenamiento, la posición en sí es la identidad y ningún estado debe seguir a una entidad de dominio. Los datos comerciales dinámicos deben recibir un ID real en lugar de depender de esas suposiciones.

Paso 4: Usar una key para expresar "este es un formulario diferente".

Un intento común de solución en páginas de detalle es:

tsx
function Profile({ userId }: { userId: string }) {
  const [comment, setComment] = useState('')

  useEffect(() => {
    setComment('')
  }, [userId])

  return <CommentForm value={comment} onChange={setComment} />
}

Esto primero renderiza el árbol con el comentario desactualizado y luego desencadena otro render después de que se ejecuta el Effect. Más importante aún, una página de detalle compleja también puede contener archivos adjuntos, errores de validación y estado de formulario anidado. Limpiar una sola variable comment no garantiza que todo el subárbol se restablezca.

Si el producto define el formulario de cada usuario como una entidad distinta, coloca la key en el límite de identidad:

tsx
function ProfilePage({ userId }: { userId: string }) {
  return <ProfileForm key={userId} userId={userId} />
}

Cuando userId cambia, React trata al nuevo ProfileForm como una identidad diferente y restablece su estado local y todo el estado de sus descendientes. Cuando un estado del padre no relacionado provoca un re-render con el mismo userId, la key se mantiene estable y el estado local se preserva.

Coloca la key en el límite completo más pequeño que deba restablecerse. Ponerle key a toda la página también recrea la navegación, vistas costosas y estados de desplazamiento no relacionados. Ponerle key a un solo input puede dejar atrás otro estado del mismo formulario.

Paso 5: Decidir qué debe preservar el producto antes de elegir un remontaje.

"Cambiar de entidad" no significa automáticamente "descartar borrador". Utiliza una tabla de decisión:

Semántica del productoDiseño de estado recomendado
Otra entidad debe recibir un formulario completamente nuevoUsa el ID de entidad como la key del subárbol del formulario
Volver a una entidad debe restaurar su borradorMantén keys de identidad; eleva los borradores y almacénalos por ID
Una recarga de página también debe restaurar los borradoresPersístelos externamente con reglas de expiración y limpieza
Restablecer un campo mientras se conserva el restoUsa estado controlado o una actualización explícita; no remontes el subárbol
Las props solo cambian un valor visual derivadoCalcúlalo a partir de las props durante el render en lugar de copiarlo en el estado

Las keys definen límites de identidad; no proporcionan persistencia a largo plazo. Una vez que el estado se eleva a drafts[userId], el subárbol de un formulario puede desmontarse mientras su borrador permanece en el padre. Al seleccionar a ese usuario nuevamente, se puede inicializar o controlar el formulario con el valor almacenado.

Paso 6: Reconocer otras causas de restablecimientos accidentales.

Incluso con keys correctas, cambiar un tipo de componente restablece el estado. Cambiar la misma posición del árbol de ProfileForm a LoginPrompt reemplaza el subárbol.

Otro error común es definir un componente dentro de otro componente:

tsx
function ProfilePage() {
  function ProfileForm() {
    const [name, setName] = useState('')
    return <input value={name} onChange={(event) => setName(event.target.value)} />
  }

  return <ProfileForm />
}

Cada renderizado de ProfilePage crea un nuevo objeto de función ProfileForm. React ve un tipo de componente diferente y, de forma inesperada, restablece el estado del input. Las definiciones de componentes deben permanecer en el nivel superior. Una respuesta centrada únicamente en las keys puede pasar por alto este error de identidad relacionado.

Paso 7: Aplicar la misma regla de identidad a listas virtualizadas.

Una lista virtualizada reutiliza repetidamente una pequeña cantidad de posiciones visibles. Si la biblioteca acepta un itemKey, devuelve el ID de la entidad de dominio en lugar del índice de la ventana. De lo contrario, desplazarse o reordenar puede hacer que una entidad herede el estado de otra posición.

Para listas grandes, un diseño aún más seguro a menudo reduce el estado comercial no persistente dentro de las filas. Almacena los borradores de edición por encima de la lista por ID de registro y permite que cada fila lea el borrador de su entidad. De esta manera, una biblioteca de virtualización puede desmontar filas fuera de pantalla sin eliminar los datos comerciales.

Paso 8: Verificar la propiedad del estado, no solo el texto renderizado.

Para cada prueba, indica qué ID debe poseer el estado:

OperaciónResultado esperado
Escribir un borrador en Alice, luego insertar a Zoe al principioEl borrador sigue perteneciendo únicamente a Alice
Eliminar un elemento intermedioEl estado de expansión e input de las otras filas no migra
Ordenar de forma descendente y luego restaurar el orden originalEl estado de cada fila continúa siguiendo a su ID de registro
Filtrar a Alice y luego quitar el filtroEl estado local de la fila se pierde tras el desmontaje; se restaura desde el almacén de borradores elevado si se requiere
Desencadenar un re-render del padre con el mismo userIdEl estado local del formulario se preserva
Cambiar del usuario A al usuario BUn formulario con key basada en userId se restablece por completo
Usar temporalmente una key aleatoria y desencadenar un re-render del padreLa pérdida de inputs y la recreación del DOM demuestran el mecanismo de fallo
Recibir IDs duplicadosAdvertir o rechazar en el límite de datos para evitar conflictos de keys entre hermanos

Las pruebas también deben cubrir el foco y los inputs no controlados. Una key incorrecta puede dejar el estado de React con una apariencia razonable mientras que los valores del DOM retenidos por el navegador o el foco se mueven al registro incorrecto. Los criterios de aceptación deben describir la continuidad de la entidad visible para los usuarios, no solo el conteo de renders.

Respuesta de muestra de alta calidad

"Trato a la key como parte de la identidad del componente, no como un atributo que simplemente elimina una advertencia de la consola. React asocia el estado con posiciones en el árbol de renderizado. Bajo un mismo padre, el mismo tipo de componente y la misma key usualmente representan la misma identidad, por lo que las actualizaciones de props o el movimiento pueden re-renderizar preservando el estado. Un tipo o una key modificados representan una nueva identidad: React elimina el subárbol anterior y monta uno nuevo.

En una lista editable, el índice identifica una posición, no un usuario. Si [Alice, Bob] usa las keys 0 y 1 y se inserta a Zoe al principio, la fila anterior con key 0 ahora puede renderizar a Zoe, por lo que el borrador o el estado expandido de Alice pueden aparecer debajo de Zoe. Yo usaría user.id, lo que mantiene estable la identidad de Alice cuando se mueve del índice 0 al índice 1. Una key aleatoria, una marca de tiempo o un UUID generado durante el render nunca coinciden con el render anterior, por lo que React recrea repetidamente los componentes y el DOM y pierde la entrada de datos. Las keys solo necesitan ser únicas entre hermanos, y el hijo no recibe key como una prop.

El formulario de detalle depende de la semántica del producto. Si pasar del usuario A al usuario B debe limpiar el formulario por completo, colocaría key={userId} en el límite de ProfileForm para que todo el estado descendiente se restablezca en conjunto en lugar de limpiar campos en varios Effects. Si volver a A debe restaurar un borrador, mantendría la identidad separada por userId pero elevaría o persistiría externamente los borradores por userId.

Finalmente, probaría la inserción al principio, la eliminación, el reordenamiento, el filtrado, los re-renders con el mismo ID y los cambios a diferentes IDs. Comprobaría que los inputs, el estado de expansión, el foco y los borradores sigan todos al ID de dominio previsto. Eso demuestra que la key modela la identidad correcta en lugar de limitarse a permitir que la página se actualice."

Errores comunes

  • Explicar las keys únicamente como una optimización de rendimiento → El problema central es la identidad de los hijos y la propiedad del estado →

Explica primero la discordancia de estado y luego el costo de actualización.

  • Usar índices de arreglos para cada lista → La inserción, eliminación, reordenamiento y filtrado cambian la correspondencia entre posición y entidad →

Usa un ID estable de los datos.

  • Generar un UUID o un valor aleatorio durante el render → La key cambia cada vez y recrea componentes y DOM →

Genera y almacena el ID cuando se crea el elemento.

  • Requerir que las keys sean globalmente únicas → React requiere unicidad entre hermanos →

Evalúa los conflictos dentro del padre y la lista actual.

  • Leer props.key en el hijo → React no pasa la key como una prop ordinaria →

Pasa una prop separada como rowId o userId.

  • Limpiar un formulario complejo campo por campo en Effects → Esto renderiza estado desactualizado, añade otro render y puede pasar por alto el estado

descendiente → Cambia la key en el límite de identidad correcto.

  • Remontar toda la página para limpiar un solo campo → Esto pierde foco, desplazamiento y estado no relacionado →

Delimita el límite de la key o actualiza el campo explícitamente.

  • Asumir que una key estable preserva el estado después de filtrar → Un componente filtrado puede haberse desmontado →

Eleva o persiste el estado cuando se requiera su restauración.

Preguntas de seguimiento

Pregunta de seguimiento 1: ¿Qué key se debe usar cuando los datos no tienen un ID de backend?

Genera un ID, como un UUID, en el evento que crea el registro local y almacénalo como un campo del registro. Cada renderizado posterior leerá el mismo ID. Una combinación inmutable y única entre hermanos de campos de dominio puede funcionar si se demuestra ese contrato. No generes la key temporalmente dentro del renderizado de map.

Pregunta de seguimiento 2: ¿Cuándo es aceptable un índice de arreglo como key?

Es relativamente seguro solo cuando la pertenencia y el orden se mantienen fijos durante toda la vida útil de la lista, no hay inserción, eliminación, filtrado ni reordenamiento, y la posición en sí es la identidad. Una visualización estática fija puede cumplir con ese límite. Los datos dinámicos de negocio deben usar IDs de entidad estables porque el ordenamiento o la edición invalidan inmediatamente las suposiciones basadas en índices.

Pregunta de seguimiento 3: Si solo un campo debe limpiarse cuando cambia userId, ¿debería cambiar la key de todo el formulario?

No necesariamente. Una key restablece el subárbol completo. Si otro estado local debe conservarse, usa un campo controlado, deriva un valor directamente de las props o ajústalo en una ruta explícita de actualización de datos. Elige un restablecimiento por key solo cuando todo el subárbol represente a otra entidad y todo su estado local deba comenzar desde cero.

Pregunta de seguimiento 4: ¿Cómo se puede restaurar un borrador después de cambiar la key?

Eleva los borradores a un padre, por ejemplo como drafts[userId], o persístelos externamente con reglas de expiración y limpieza. Mantén la key del formulario basada en userId para que diferentes usuarios no compartan el estado local. Un formulario recién montado lee su valor inicial del borrador almacenado correspondiente. El aislamiento de identidad y la persistencia de borradores son responsabilidades separadas.

Pregunta de seguimiento 5: ¿Una lista virtualizada todavía necesita keys estables si ya reutiliza el DOM?

Sí. La virtualización controla el número de nodos visibles; no redefine la identidad del dominio. Si la biblioteca expone itemKey, devuelve el ID del registro. El estado de edición que deba sobrevivir al desmontaje también debe residir por encima de las filas por ID, o de lo contrario desaparecerá cuando una fila se desplace fuera de la ventana visible.

Fuentes públicas

Preguntas relacionadas