Cuando se trabaja con React, es mejor usar componentes reutilizables con herramientas como  Bit para evitar tener que reescribirlos cada vez. Además, es bueno tener los componentes organizados en una galería visual, ¿no es así?

Formulación del problema

Intente renderizar múltiples componentes de React como este:

class ParentC extends React.Component {
    render() {
        return (
            <ChildC />
            <ChildC />
        )
    }
}

class ChildC extends React.Component {
    render() {
        return (
            <h1>
                Child Component
            </h1>
        )
    }
}

o crea una lista de nodos como esta:

class ChildComponent extends React.Component {
    render() {
        return (
            <h1>Hello Child Component</h1>
            <h1>Hello Child Component</h1>
        )
    }
}

Al usar VS Code con extensiones de compatibilidad con JSX, aparecerá una advertencia: "Las expresiones JSX principales deben tener un único elemento principal".

Para que desaparezca la advertencia, debe agregar una etiqueta div adicional como elemento principal al marcado JSX.

class ParentC extends React.Component {
    render() {
        return (
            <div>
                <ChildComponent />
                <ChildComponent />
            </div>
        )
    }
}

class ChildComponent extends React.Component {
    render() {
        return (
            <div>
                <h1>Hello Child Component</h1>
                <h1>Hello Child Component</h1>
            </div>
        )
    }
}

El problema es que usar etiquetas div es un poco incómodo. Hay casos en HTML donde un div adicional puede desestructurar el DOM. Por ejemplo, al usar una tabla en componentes.

Necesitamos representar los datos del usuario en forma tabular usando el elemento de tabla HTML. Necesitamos renderizar el siguiente código en React:

<table>
    <tr>
        <th>Name</th>
        <th>Occupation</th>
        <th>Age</th>
    </tr>
    <tr>
        <td>Chidume Nnamdi</td>
        <td>Software Dev</td>
        <td>27</td>
    </tr>
    <tr>
        <td>Row Ekemezie</td>
        <td>Software Dev</td>
        <td>? :)</td>
    </tr>
</table>

Vamos a crear componentes para representar cada aspecto del elemento de la tabla. HeaderComponent mostrará el encabezado de la tabla, BodyComponent - el cuerpo de la tabla. El TableComponent representa un esqueleto de tabla con un HeaderComponent y un BodyComponent así:

class TableComponent extends React.Component {
    render() {
        return (
            <table>
                <tr>
                    <HeaderComponent />
                </tr>
                <tr>
                    <BodyComponent />
                </tr>
            </table>
        )
    }
}

HeaderComponent debería verse así:

class HeaderComponent extends React.Component {
    render() {
        return (
            <th>Name</th>
            <th>Occupation</th>
            <th>Age</th>            
        )
    }
}

Y el BodyComponent se ve así:

class BodyComponent extends React.Component {
    render() {
        return (
            <td>Chidume Nnamdi</td>
            <td>Software Dev</td>
            <td>27</td>
        )
    }
}

El problema con HeaderComponent y BodyComponent es que devuelven varios nodos. React le advertirá que anide el marcado en una etiqueta anidada.

Luego realizamos acciones similares para eliminar la advertencia:

class HeaderComponent extends React.Component {
    render() {
        return (
            <div>
                <th>Name</th>
                <th>Occupation</th>
                <th>Age</th>                        
            </div>
        )
    }
}

class BodyComponent extends React.Component {
    render() {
        return (
            <div>
                <td>Chidume Nnamdi</td>
                <td>Software Dev</td>
                <td>27</td>            
            </div>
        )
    }
}

El marcado está anidado dentro de una etiqueta div. Ahora la salida del componente Tabla se verá así:

<table>
    <tr>
        <div>
            <th>Name</th>
            <th>Occupation</th>
            <th>Age</th>
        </div>
    </tr>
    <tr>
        <div>
            <td>Chidume Nnamdi</td>
            <td>Software Dev</td>
            <td>27</td>
        </div>
    </tr>
</table>

Lo anterior es una salida incorrecta del elemento de la tabla. El elemento div no debe representarse. Los componentes de React están diseñados para devolver elementos, pero deben incluirse en una etiqueta principal; no se pueden devolver varios elementos. Sin embargo, agregar un nodo adicional a veces hace que el elemento de salida html tenga un formato incorrecto, como se muestra arriba.

¿Cómo resolver este problema? ¿Cómo puede devolver elementos JSX adjuntos sin afectar la salida renderizada en el DOM?

¡Los fragmentos de React pueden resolver este problema!

Solución - Fragmentos

Los fragmentos le permiten agrupar una lista de elementos secundarios sin agregar nodos adicionales al DOM.

Con  <React.Fragment>...</React.Fragment>, puede agregar una etiqueta principal a los elementos JSX sin agregar un nodo adicional al DOM. React.Fragment no genera HTMLElement.

Comencemos con el primer problema:

class ParentC extends React.Component {
    render() {
        return (
            <ChildC />
            <ChildC />
        )
    }
}

class ChildC extends React.Component {
    render() {
        return (
            <h1>
                Child Component
            </h1>
        )
    }
}

Ahora vamos a hacer el anidamiento:

return (
            <ChildC />
            <ChildC />
        )

en  React.Fragment. Obtenemos este resultado:

class ParentC extends React.Component {
    render() {
        return (
            <React.Fragment>
                <ChildC />
                <ChildC />
            </React.Fragment>
        )
    }
}

Pasemos al segundo ejemplo:

class ParentC extends React.Component {
    render() {
        return (
            <div>
                <ChildComponent />
                <ChildComponent />
            </div>
        )
    }
}

class ChildComponent extends React.Component {
    render() {
        return (
            <div>
                <h1>Hello Child Component</h1>
                <h1>Hello Child Component</h1>
            </div>
        )
    }
}

Quite las etiquetas  div y agregue  React.Fragment en su lugar:

class ParentC extends React.Component {
    render() {
        return (
            <React.Fragment>
                <ChildComponent />
                <ChildComponent />
            </React.Fragment>
        )
    }
}

class ChildComponent extends React.Component {
    render() {
        return (
            <React.Fragment>
                <h1>Hello Child Component</h1>
                <h1>Hello Child Component</h1>
            </React.Fragment>
        )
    }
}

Pasando al tercer ejemplo, reemplazamos las etiquetas div adicionales en BodyComponent y HeaderComponent con React.Fragment:

class HeaderComponent extends React.Component {
    render() {
        return (
            <div>
                <th>Name</th>
                <th>Occupation</th>
                <th>Age</th>                        
            </div>
        )
    }
}

class BodyComponent extends React.Component {
    render() {
        return (
            <div>
                <td>Chidume Nnamdi</td>
                <td>Software Dev</td>
                <td>27</td>            
            </div>
        )
    }
}

|
    |
    |
    v

class HeaderComponent extends React.Component {
    render() {
        return (
            <React.Fragment>
                <th>Name</th>
                <th>Occupation</th>
                <th>Age</th>                        
            </React.Fragment>
        )
    }
}

class BodyComponent extends React.Component {
    render() {
        return (
            <React.Fragment>
                <td>Chidume Nnamdi</td>
                <td>Software Dev</td>
                <td>27</td>            
            </React.Fragment>
        )
    }
}

La tabla se mostrará de la siguiente manera:

<table>
    <tr>
        <th>Name</th>
        <th>Occupation</th>
        <th>Age</th>
    </tr>
    <tr>
        <td>Chidume Nnamdi</td>
        <td>Software Dev</td>
        <td>27</td>
    </tr>
</table>

Tal como queríamos, ¡sin etiquetas div adicionales!

Si encuentra que  React.Fragmenttarda demasiado en escribirlo una y otra vez, puede usar la sintaxis abreviada. Se parece a esto:  <>...</>. Ahora los componentes se   ven así BodyComponent : HeaderComponent

class HeaderComponent extends React.Component {
    render() {
        return (
            <React.Fragment>
                <th>Name</th>
                <th>Occupation</th>
                <th>Age</th>                        
            </React.Fragment>
        )
    }
}

class BodyComponent extends React.Component {
    render() {
        return (
            <React.Fragment>
                <td>Chidume Nnamdi</td>
                <td>Software Dev</td>
                <td>27</td>            
            </React.Fragment>
        )
    }
}

También se puede escribir de esta forma:

class HeaderComponent extends React.Component {
    render() {
        return (
            <>
                <th>Name</th>
                <th>Occupation</th>
                <th>Age</th>                        
            </>
        )
    }
}

class BodyComponent extends React.Component {
    render() {
        return (
            <>
                <td>Chidume Nnamdi</td>
                <td>Software Dev</td>
                <td>27</td>            
            </>
        )
    }
}

Conclusión

Analizamos el problema de no poder devolver múltiples elementos y cómo resolverlo usando React.Fragment, y también aprendimos cómo usar la sintaxis abreviada de React.Fragment.

Con React.Fragment, puede disfrutar del beneficio de devolver múltiples elementos sin tener que agregar etiquetas adicionales o etiquetas div que rodean los elementos y saturan el DOM.


Chidume  Nnamdi :  comprensión de fragmentos en React

Compartir:
Categorías: Programación

0 comentarios

Deja una respuesta

Marcador de posición del avatar

Tu dirección de correo electrónico no será publicada.

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.