Renderizado de listas
A menudo querrås mostrar muchos componentes similares de una colección de datos. Puedes usar los métodos de array de JavaScript para manipular un array de datos. En esta pågina, usarås filter()
y map()
con React para filtrar y transformar tu array de datos en un array de componentes.
AprenderĂĄs
- Cómo renderizar componentes desde un array usando el método
map()
de JavaScript - CĂłmo renderizar solo un componente especĂfico usando
filter()
de JavaScript - CuĂĄndo y cĂłmo usar las keys de React
Renderizar datos desde arrays
Digamos que tienes una lista de contenido.
<ul>
<li>Creola Katherine Johnson: matemĂĄtica</li>
<li>Mario JosĂ© Molina-Pasquel HenrĂquez: quĂmico</li>
<li>Mohammad Abdus Salam: fĂsico</li>
<li>Percy Lavon Julian: quĂmico</li>
<li>Subrahmanyan Chandrasekhar: astrofĂsico</li>
</ul>
La Ășnica diferencia entre esos elementos de la lista es su contenido, sus datos. A menudo necesitarĂĄs mostrar muchas instancias del mismo componente usando diferentes datos cuando construyas interfaces: desde listas de comentarios a galerĂas de fotos de perfiles. En estas situaciones, puedes guardar estos datos en objetos de JavaScript y arrays, y usar mĂ©todos como map()
y filter()
para renderizar listas de componentes desde ellos.
AquĂ hay un corto ejemplo de como generar una lista de elementos de un array:
- Mueve los datos en un array:
const people = [
'Creola Katherine Johnson: matemĂĄtica',
'Mario JosĂ© Molina-Pasquel HenrĂquez: quĂmico',
'Mohammad Abdus Salam: fĂsico',
'Percy Lavon Julian: quĂmico',
'Subrahmanyan Chandrasekhar: astrofĂsico'
];
- Mapea los miembros de
people
en un nuevo array de nodos JSX,listItems
:
const listItems = people.map(person => <li>{person}</li>);
- Devuelve
listItems
desde tu componente envuelto en un<ul>
:
return <ul>{listItems}</ul>;
AquĂ estĂĄ el resultado:
const people = [ 'Creola Katherine Johnson: matemĂĄtica', 'Mario JosĂ© Molina-Pasquel HenrĂquez: quĂmico', 'Mohammad Abdus Salam: fĂsico', 'Percy Lavon Julian: quĂmico', 'Subrahmanyan Chandrasekhar: astrofĂsico' ]; export default function List() { const listItems = people.map(person => <li>{person}</li> ); return <ul>{listItems}</ul>; }
Date cuenta que el sandbox anterior muestra un error por consola:
Aprenderås como arreglar este error mås adelante en esta pågina. Antes de que lleguemos a eso, vamos a añadir algo de estructura a tus datos.
Filtrar arrays de objetos
Estos datos pueden ser estructurados incluso mĂĄs.
const people = [{
id: 0,
name: 'Creola Katherine Johnson',
profession: 'matemĂĄtica',
}, {
id: 1,
name: 'Mario JosĂ© Molina-Pasquel HenrĂquez',
profession: 'quĂmico',
}, {
id: 2,
name: 'Mohammad Abdus Salam',
profession: 'fĂsico',
}, {
id: 3,
name: 'Percy Lavon Julian',
profession: 'quĂmico',
}, {
id: 4,
name: 'Subrahmanyan Chandrasekhar',
profession: 'astrofĂsico',
}];
Digamos que quieres una manera de mostrar solo las personas cuya profesiĂłn sea 'quĂmico'
. Puedes usar el método filter()
de JavaScript para devolver solo esas personas. Este mĂ©todo coge un array de objetos, los pasa por un âtestâ (una funciĂłn que devuelve true
o false
), y devuelve un nuevo array de solo esos objetos que han pasado el test (que han devuelto true
).
TĂș solo quieres los objetos donde profession
es 'quĂmico'
. La funciĂłn âtestâ para esto se ve como (person) => person.profession === 'quĂmico'
. AquĂ estĂĄ cĂłmo juntarlo:
- Crea un nuevo array solo de personas que sean âquĂmicosâ,
chemists
, llamando al métodofilter()
enpeople
filtrando porperson.profession === 'quĂmico'
:
const chemists = people.filter(person =>
person.profession === 'quĂmico'
);
- Ahora mapea sobre
chemists
:
const listItems = chemists.map(person =>
<li>
<img
src={getImageUrl(person)}
alt={person.name}
/>
<p>
<b>{person.name}:</b>
{' ' + person.profession + ' '}
conocido/a por {person.accomplishment}
</p>
</li>
);
- Por Ășltimo, devuelve el
listItems
de tu componente:
return <ul>{listItems}</ul>;
import { people } from './data.js'; import { getImageUrl } from './utils.js'; export default function List() { const chemists = people.filter(person => person.profession === 'quĂmico' ); const listItems = chemists.map(person => <li> <img src={getImageUrl(person)} alt={person.name} /> <p> <b>{person.name}:</b> {' ' + person.profession + ' '} conocido/a por {person.accomplishment} </p> </li> ); return <ul>{listItems}</ul>; }
Mantener los elementos de una lista en orden con key
FĂjate que todos los sandboxes anteriores mostraban un error en la consola:
Tienes que darle a cada elemento del array una key
(una cadena de texto o un nĂșmero) que lo identifique de manera Ășnica entre otros elementos del array:
<li key={person.id}>...</li>
Las keys le indican a React que objeto del array corresponde a cada componente, para asĂ poder emparejarlo mĂĄs tarde. Esto se vuelve mĂĄs importante si los objetos de tus arrays se pueden mover (p. ej. debido a un ordenamiento), insertar, o eliminar. Una key
bien escogida ayuda a React a entender lo que ha sucedido exactamente, y hacer las correctas actualizaciones en el ĂĄrbol del DOM.
En vez de generar keys sobre la marcha, deberĂas incluirlas en tus datos:
export const people = [{ id: 0, // Usado en JSX como key name: 'Creola Katherine Johnson', profession: 'matemĂĄtica', accomplishment: 'los cĂĄlculos de vuelos espaciales', imageId: 'MK3eW3A' }, { id: 1, // Usado en JSX como key name: 'Mario JosĂ© Molina-Pasquel HenrĂquez', profession: 'quĂmico', accomplishment: 'el descubrimiento del agujero de ozono en el Ărtico', imageId: 'mynHUSa' }, { id: 2, // Usado en JSX como key name: 'Mohammad Abdus Salam', profession: 'fĂsico', accomplishment: 'la teorĂa del electromagnetismo', imageId: 'bE7W1ji' }, { id: 3, // Usado en JSX como key name: 'Percy Lavon Julian', profession: 'quĂmico', accomplishment: 'ser pionero en el uso de cortisona, esteroides y pĂldoras anticonceptivas', imageId: 'IOjWm71' }, { id: 4, // Usado en JSX como key name: 'Subrahmanyan Chandrasekhar', profession: 'astrofĂsico', accomplishment: 'los cĂĄlculos de masa de estrellas enanas blancas', imageId: 'lrWQx8l' }];
Profundizar
¿Qué haces cuåndo cada objeto necesita renderizar no uno, sino varios nodos del DOM?
El atajo de sintaxis del <>...</>
Fragment no te dejarĂĄ pasarle una key, asĂ que necesitas agruparlos en un solo <div>
, o usar una sintaxis algo mĂĄs larga y mĂĄs explĂcita del <Fragment>
:
import { Fragment } from 'react';
// ...
const listItems = people.map(person =>
<Fragment key={person.id}>
<h1>{person.name}</h1>
<p>{person.bio}</p>
</Fragment>
);
Los Fragments desaparecen del DOM, asĂ que esto producirĂĄ una lista plana de <h1>
, <p>
, <h1>
, <p>
, y asĂ.
DĂłnde conseguir tu key
Distintas fuentes de datos dan diferentes fuentes de keys:
- Datos de una base de datos: Si tus datos vienen de una base de datos, puedes usar las keys/ID de la base de datos, que son Ășnicas por naturaleza.
- Datos generados localmente: Si tus datos son generados y persistidos localmente (p. ej. notas en una app de tomar notas), usa un contador incremental,
crypto.randomUUID()
o un paquete comouuid
cuando este creando objetos.
Reglas de las keys
- Las keys tienen que ser Ășnicas entre elementos hermanos. Sin embargo, estĂĄ bien usar las mismas keys para nodos JSX en arrays diferentes.
- Las keys no tienen que cambiar o ÂĄeso quitarĂĄ su propĂłsito! No las generes mientras renderizas.
¿Por qué React necesita keys?
Imagina que los archivos de tu escritorio no tuvieran nombres. En vez de eso, tu te referirĂas a ellos por su orden â el primer archivo, el segundo, y asĂ. PodrĂas acostumbrarte a ello, pero una vez borres un archivo, se volverĂa algo confuso. El segundo archivo se convertirĂa en el primero, el tercer archivo se convertirĂa en el segundo, y asĂ.
Los nombres de archivos en una carpeta y las keys JSX en un array tienen un propĂłsito similar. Nos permiten identificar un objeto de manera Ășnica entre sus hermanos. Una key bien escogida da mĂĄs informaciĂłn aparte de la posiciĂłn en el array. incluso si la posiciĂłn cambia debido a un reordenamiento, la key
permite a React identificar al elemento a lo largo de su ciclo de vida.
RecapitulaciĂłn
En esta pĂĄgina has aprendido:
- Como mover datos fuera de componentes y en estructuras de datos como arrays y objetos.
- Como genrerar sets de componentes similares con el método
map()
de JavaScript. - Como crear arrays de objetos filtrados con el método
filter()
de JavaScript. - Por qué y cómo poner la
key
en cada componente en una colecciĂłn para que React pueda seguir la pista de cada uno de ellos incluso si su posiciĂłn o datos cambia.
DesafĂo 1 de 4: Dividir una lista en dos
Este ejemplo muestra una lista de todas las personas.
Cambiala para mostrar dos listas separadas, una detrĂĄs de otra : QuĂmicos y Todos los demĂĄs. Como antes, puedes saber que persona es quĂmica comprobando si person.profession === 'quĂmico'
.
import { people } from './data.js'; import { getImageUrl } from './utils.js'; export default function List() { const listItems = people.map(person => <li key={person.id}> <img src={getImageUrl(person)} alt={person.name} /> <p> <b>{person.name}:</b> {' ' + person.profession + ' '} conocido/a por {person.accomplishment} </p> </li> ); return ( <article> <h1>CientĂficos</h1> <ul>{listItems}</ul> </article> ); }