We want to hear from you!Take our 2020 Community Survey!

Llistes i Claus

Primer, revisem com es transformen les llistes a JavaScript.

En el codi que segueix a sota, utilitzem la funció map() per prendre una matriu de numeros i duplicar-ne els seus valors. Assignem la nova array retornada per map() a la variable doblat i la mostrem a la consola:

const numeros = [1, 2, 3, 4, 5];
const doblat = numeros.map((num) => num * 2);console.log(doblat);

Aquest codi mostra [2, 4, 6, 8, 10] a la consola.

A React, transformar arrays en llistes d’elements és gairebé idèntic.

Renderització de múltiples components

Podem construir col·leccions d’elements i incloure-les a JSX fent servir claus {}.

A continuació, farem servir el mètode de Javascript map() a l’array numeros. Aquest ens retornarà un element <li> per a cada element de l’array. Després, assignarem l’array resultant a la variable llistaDElements

const numeros = [1, 2, 3, 4, 5];
const llistaDElements = numeros.map((numero) =>  <li>{numero}</li>);

Finalment, incloem tota la llista sencera dins un element <ul>, i la renderitzem al DOM:

ReactDOM.render(
  <ul>{llistaDElements}</ul>,  document.getElementById('root')
);

Prova-ho a CodePen

Aquest codi mostra una llista de números entre l’1 i el 5.

Component de llista bàsic

Normalment renderitzaràs les llistes dins d’un component.

Podem refer l’exemple anterior fent un component que accepti una array de numeros i generi una llista d’elements.

function LlistaNumeros(props) {
  const numeros = props.numeros;
  const llistaDElements = numeros.map((numero) =>    <li>{numero}</li>  );  return (
    <ul>{llistaDElements}</ul>  );
}

const numeros = [1, 2, 3, 4, 5];
ReactDOM.render(
  <LlistaNumeros numeros={numeros} />,  document.getElementById('root')
);

Quan executis aquest codi rebràs un avís que diu que s’ha de donar una clau (key) a cada element de la llista. Una clau (key) és un atribut de cadena especial que has d’incloure en crear llistes d’elements. Parlarem de per què és important a la següent secció.

Assignem doncs, una clau (key) als elements de la nostra llista dins de numeros.map() que corregeixi el problema de la clau que falta.

function LlistaNumeros(props) {
  const numeros = props.numeros;
  const llistaDElements = numeros.map((numero) =>
    <li key={numero.toString()}>      {numero}
    </li>
  );
  return (
    <ul>{llistaDElements}</ul>
  );
}

const numeros = [1, 2, 3, 4, 5];
ReactDOM.render(
  <LlistaNumeros numeros={numeros} />,
  document.getElementById('root')
);

Prova-ho a CodePen

Claus

Les claus ajuden React a identificar quins elements han canviat, afegit o eliminat. Les claus s’han de donar als elements de dins de l’array per donar-los una identitat estable:

const numeros = [1, 2, 3, 4, 5];
const llistaDElements = numeros.map((numero) =>
  <li key={numero.toString()}>    {numero}
  </li>
);

La millor manera de triar una clau és fer servir una cadena que identifiqui de manera única un element de la llista d’entre tots els altres elements d’aquesta mateixa llista. Molt sovint faràs servir la ID de les dades com a claus:

const todoItems = todos.map((todo) =>
  <li key={todo.id}>    {todo.text}
  </li>
);

Quan no tinguis més remei perquè no tens una ID estable per a cada elements de la llista, pots fer servir l’índex de l’element com a clau:

const todoItems = todos.map((todo, index) =>
  // Fes-ho només quan els elements no tinguin una ID estable  <li key={index}>    {todo.text}
  </li>
);

No et recomanem que facis servir els índexs per a les claus si l’ordre dels elements pot canviar. Això pot afectar negativament el rendiment i pot causar problemes amb l’estat del component. Llegeix l’article de Robin Pokorny que dóna una explicació en profunditat sobre els impactes negatius d’utilitzar un índex com a clau. Si tries no assignar una clau explícita als elements de la llista, React farà servir els índexs com a claus per defecte.

Aquí hi trobaràs una explicació en profunditat sobre per què les claus són necessàries si estàs interessat en saber-ne més.

Identificant components amb claus

Les claus només tenen sentit en el context de l’array a la que pertanyen.

Per exemple, si extreus un component ElementDeLaLlista, hauràs de donar la clau a l’element <ElementDeLaLlista /> de l’array enlloc de a l’element <li> de la pròpia llista LlistadElemets.

Exemple: Ús incorrecte de ‘key’

function LlistadElemets(props) {
  const valor = props.valor;
  return (
    // Malament! No hi ha cap necessitat d'especificar una clau ('key') aquí:    <li key={valor.toString()}>      {valor}
    </li>
  );
}

function LlistaDeNumeros(props) {
  const numeros = props.numeros;
  const LlistadElemets = numeros.map((numeros) =>
    // Malament! La clau hauria d'haver sigut especificada aquí:    <ElementDeLaLlista valor={numero} />  );
  return (
    <ul>
      {LlistadElemets}
    </ul>
  );
}

const numeros = [1, 2, 3, 4, 5];
ReactDOM.render(
  <LlistaDeNumeros numeros={numeros} />,
  document.getElementById('root')
);

Exemple: Ús correcte de ‘key’

function ElementDeLaLlista(props) {
  // Correcte! No cal especificar la clau aquí:  return <li>{props.valor}</li>;}

function LlistaDeNumeros(props) {
  const numeros = props.numeros;
  const LlistadElemets = numeros.map((numeros) =>
    // Correcte! La clau ha de ser especificada dins de l'array.    <ElementDeLaLlista key={numero.toString()} valor={numero} />  );
  return (
    <ul>
      {LlistadElemets}
    </ul>
  );
}

const numeros = [1, 2, 3, 4, 5];
ReactDOM.render(
  <LlistaDeNumeros numeros={numeros} />,
  document.getElementById('root')
);

Prova-ho a CodePen

Una bona regla d’or, que pots fer servir, és saber que els elements inclosos dins del mètode map() necessiten una clau.

Les claus han de ser úniques només entre els elements de la mateixa array (germans)

Les claus que es fan servir dins de les matrius han de ser úniques entre els seus germans. No obstant, no necessiten ser globalment úniques. Podem fer servir les mateixes claus quan produïm dos arrays diferents:

function Blog(props) {
  const barraLateral = (    <ul>
      {props.posts.map((post) =>
        <li key={post.id}>          {post.titol}
        </li>
      )}
    </ul>
  );
  const contingut = props.posts.map((post) =>    <div key={post.id}>      <h3>{post.titol}</h3>
      <p>{post.contingut}</p>
    </div>
  );
  return (
    <div>
      {barraLateral}      <hr />
      {contingut}    </div>
  );
}

const posts = [
  {id: 1, titol: 'Hola Món', contingut: "Benvinguts a l'aprenentatge de React!"},
  {id: 2, titol: 'Instal·lació', contingut: 'Pots instal·lar React des de npm.'}
];
ReactDOM.render(
  <Blog posts={posts} />,
  document.getElementById('root')
);

Prova-ho a CodePen

Les claus serveixen com a una ajuda per a React però no es passen als components. Si necessites el mateix valor en el teu component, passa’l explícitament com un atribut amb un nom diferent:

const contingut = posts.map((post) =>
  <Post
    key={post.id}    id={post.id}    titol={post.titol} />
);

A l’exemple anterior, el component Post pot llegir props.id, però no props.key.

Incrustant map() dins de JSX

En els exemples anteriors hem declarat una variable listItems separada i l’hem inclòs dins el JSX:

function LlistaDeNumeros(props) {
  const numeros = props.numeros;
  const llistaDElements = numeros.map((numero) =>    <ElementDeLaLlista key={numero.toString()}              valor={numero} />  );  return (
    <ul>
      {llistaDElements}
    </ul>
  );
}

JSX permet incrustar expressions tancades entre claus de manera que podem tenir-hi el resultat de map():

function LlistaDeNumeros(props) {
  const numeros = props.numeros;
  return (
    <ul>
      {numeros.map((numero) =>        <ElementDeLaLlista key={numero.toString()}                  valor={numero} />      )}    </ul>
  );
}

Prova-ho a CodePen

A vegades amb això queda en un codi més clar, però mira de no fer-ne un abús. Com a JavaScript, depèn de tu decidir si val la pena extreure una variable per a la llegibilitat del codi. Tingues en compte que si el cos de map() és massa imbricat, pot ser un bon moment per extreure un component.

Is this page useful?Edit this page