Menu

Fragment en React: <>...</> vs <Fragment> con ejemplos

Un Fragment de React agrupa varios elementos en un solo valor de retorno sin agregar un nodo a la página. Aprende la sintaxis corta <>...</>, cuándo necesitas <Fragment key> y por qué los fragmentos importan dentro de tablas y listas.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Un Fragment de React permite a un componente devolver varios elementos sin envolverlos en un <div> extra. Escribe <> antes del primer elemento y </> después del último, y React pone los elementos directamente dentro del padre, sin ningún nodo propio en la página.

Cada Greeting devuelve un título y un párrafo uno al lado del otro. Borra las líneas <> y </> y la vista previa muestra un error de build, porque la función ahora intenta devolver dos valores.

Por qué un componente necesita una sola raíz

JSX es una forma más cómoda de escribir llamadas a funciones. <h2>Hi</h2> se compila aproximadamente a jsx('h2', { children: 'Hi' }), una expresión. Una sentencia return puede devolver un valor, así que dos etiquetas hermanas sin nada alrededor son como escribir return a b: el compilador se detiene con "Adjacent JSX elements must be wrapped in an enclosing tag".

Antes de que existieran los fragmentos, la solución era un <div> envoltorio. Funciona, pero el div es un elemento real. Aparece en el DOM, participa en el layout de CSS y algunos padres directamente no lo aceptan como hijo. Un fragmento cumple la regla de una sola raíz y luego desaparece.

Puedes comprobar que no agrega nada. El ejemplo de abajo renderiza los mismos dos elementos a través de un fragmento y a través de un div, y luego cuenta los hijos directos de cada contenedor.

La consola imprime 2 para el fragmento, los dos spans, y 1 para el div, que los envuelve. En un contenedor flex o grid esa diferencia decide si los spans se distribuyen como elementos o quedan agrupados en uno.

Sintaxis corta y el componente Fragment

Hay dos formas de escribir un fragmento, y se compilan a lo mismo:

import { Fragment } from 'react';

// Short syntax, no import needed
<>
    <dt>React</dt>
    <dd>A library for building user interfaces</dd>
</>

// Long form
<Fragment>
    <dt>React</dt>
    <dd>A library for building user interfaces</dd>
</Fragment>

Usa <>...</> casi en todas partes. Recurre a <Fragment> en un caso: cuando el fragmento necesita una key. La sintaxis corta no acepta atributos, así que <key={id}> no es JSX válido. También puedes ver <React.Fragment> en código antiguo; es el mismo componente accedido mediante la importación por defecto de React.

Fragmentos con key en listas

Cuando renderizas una lista con map, cada elemento necesita una key para que React pueda seguirlo entre renderizados (la página sobre listas y keys explica por qué). Si cada elemento es un grupo de elementos en lugar de uno solo, la key va en el fragmento, así que necesitas la forma larga.

Una lista de descripción es el caso clásico: cada entrada es un <dt> y un <dd>, y un <dl> debe contenerlos directamente.

Haz clic en Reverse y los pares cambian de lugar como unidades completas, porque cada par tiene su propia key. Un <div> envoltorio alrededor de cada par también aceptaría una key, y es HTML válido dentro de un dl, pero agrega un tercer nivel al marcado que un fragmento evita.

Fragmentos dentro de tablas

Las tablas son donde un envoltorio de más hace más daño. Un <tr> espera celdas <td> y <th> como hijos directos. Si un componente que devuelve varias celdas las envuelve en un <div>, el navegador trata el div como una celda extraña y las celdas que contiene dejan de alinearse con el encabezado.

La fila del fragmento tiene su precio bajo Price y su stock bajo Stock. En la fila del div ambas celdas quedan apretadas en la columna Price y la columna Stock queda vacía. En desarrollo React también registra una advertencia de que un <div> no puede ser hijo de un <tr>; la vista previa funciona como un build de producción, así que omite esa comprobación, y lo que ves aquí es el layout roto. Con renderizado en el servidor, el mismo error también puede causar errores de hidratación, porque el parser HTML del navegador mueve el div mal colocado.

La misma regla se aplica a <ul> y <ol>, que deben contener elementos <li>, y a <select>, que debe contener elementos <option>. Siempre que un componente devuelva piezas que van directamente dentro de un padre así, devuelve un fragmento.

Fragmentos o arrays

Un componente también puede devolver un array de elementos, y React los renderiza en orden como un fragmento. Cada elemento de un array devuelto necesita su propia key, igual que la salida de map, porque React trata el array como una lista:

function Cells() {
    return [<td key="price">$4</td>, <td key="stock">In stock</td>];
}

Funciona, pero es más ruidoso: comas entre elementos, una key en cada uno y un corchete fácil de pasar por alto cuando el marcado crece. Usa un fragmento para un grupo fijo de elementos, y deja los arrays para lo que son de forma natural, el resultado de mapear datos.

Lo que un fragmento no puede hacer

Como un fragmento no renderiza ningún elemento, no tiene dónde poner una clase, un estilo, un manejador de eventos o una ref. <Fragment className="row"> no hace nada útil, y la única prop que React lee de un fragmento es key. Cuando necesitas dar estilo al grupo o escuchar clics sobre él, al final necesitas un elemento real, y eso está bien: elige uno que sea válido donde está, como un <tbody> para agrupar filas o un <li> para contener un elemento de lista.

Un fragmento funciona en cualquier lugar donde funciona un elemento, incluido el renderizado condicional: {show && <>...</>} muestra u oculta todo el grupo a la vez.

Preguntas frecuentes

¿Qué es un Fragment en React?

Un Fragment es un envoltorio que permite a un componente devolver varios elementos como un solo valor sin agregar un nodo al DOM. <><h1 /><p /></> pone el h1 y el p directamente dentro del padre.

¿Cuál es la diferencia entre <> y <Fragment>?

Producen lo mismo. <>...</> es la sintaxis corta. <Fragment> es la forma larga que importas desde react, y es la única que puede recibir una key, que necesitas cuando renderizas fragmentos en una lista.

¿Por qué usar un Fragment en lugar de un div?

Un div es un elemento real. Puede romper layouts que esperan hijos directos (contenedores flex y grid, ul, table, tr) y agrega ruido al DOM. Un Fragment no agrega nada.

¿Un Fragment puede tener className u onClick?

No. Un Fragment no renderiza ningún elemento, así que no hay dónde poner una clase, un estilo o un manejador de eventos. La única prop que acepta es key. Si necesitas alguna de esas cosas, usa un elemento real.

¿Por qué aparece "Adjacent JSX elements must be wrapped in an enclosing tag"?

Un componente devolvió dos elementos hermanos sin nada alrededor. JSX se compila a una sola expresión, así que envuelve los hermanos en <>...</>.

Ilustración de los lenguajes de programación de Coddy

Aprende a programar con Coddy

COMENZAR