Il ruolo cruciale della "chiave" nella mappatura degli array
Se sei qualcuno che tende a ignorare il messaggio di avviso "ogni elemento dovrebbe avere una chiave univoca" durante la mappatura di un array in React, è importante prendersi un momento per capire perché questo avviso viene generato in primo luogo.
In React, quando si esegue il rendering di un elenco di elementi utilizzando la funzione "Array.map()", si consiglia di fornire una prop "chiave" univoca per ciascun elemento. Ma perché?
La risposta è l'ottimizzazione.
Consideriamo che stiamo costruendo un negozio di e-commerce in cui abbiamo il nostro carrello e stiamo usando un array per memorizzare gli articoli che un utente ha aggiunto al proprio carrello. L'array può essere aggiornato dinamicamente man mano che l'utente aggiunge o rimuove elementi.
Supponiamo che il nostro caro utente stia acquistando un laptop nuovo di zecca e abbia attualmente 3 articoli nel suo carrello, ovvero 3 elementi dell'array.
Supponiamo ora che l'utente aggiunga le “ cuffie” al suo carrello. Ora che stiamo memorizzando l'array in uno stato, nel momento in cui un utente aggiunge o rimuove qualcosa dall'array, React eseguirà nuovamente il rendering del componente in modo che l'interfaccia utente possa essere sincronizzata con l'ultimo valore dello stato di quel particolare componente.
Giocherà al gioco "trova le differenze" per scoprire cosa è cambiato rispetto al rendering precedente e aggiornare l'interfaccia utente di conseguenza. Rileverà che c'è un nuovo elemento nell'albero DOM virtuale corrente che non era presente nel precedente albero DOM virtuale e aggiungerà il nuovo elemento al DOM senza confrontarlo con gli elementi esistenti nell'array (questo perché React ha già confrontato i DOM virtuali e sa che il nuovo elemento è l'unico elemento che è cambiato). Non abbiamo le cuffie, quindi le inseriamo. Vai tranquillo!
Quindi ora il nostro array di carrelli sarà mappato in questo modo:
Ma ora, supponiamo che il negozio consenta agli utenti di ordinare gli articoli nel carrello in base al prezzo, dal più basso al più alto. Di conseguenza, l'ordine degli articoli nel carrello cambia e il carrello viene ora visualizzato come segue: mouse, cuffie, tastiera e laptop.
Qui, React deve nuovamente confrontare l'intero DOM virtuale per determinare le modifiche, poiché non aveva altro modo per sapere che gli elementi erano stati semplicemente riordinati e non era cambiato un singolo elemento dell'array . Genererà un nuovo albero DOM virtuale che riflette il nuovo ordine degli elementi. Confronterà quindi ciascun elemento nel precedente albero DOM virtuale con l'elemento corrispondente nel nuovo albero DOM virtuale per determinare le modifiche.
Non sarebbe bello se React potesse conoscere la differenza tra quando gli elementi dell'array sono appena riordinati e quando sono effettivamente cambiati (aggiunti o rimossi) e anche l'elemento esatto che è stato aggiunto o rimosso in modo da poter ottimizzare la differenza del DOM virtuale elaborare e migliorare le prestazioni?
Sì, possiamo, e la risposta è attraverso l'elica "chiave".
Diciamo che aggiungiamo una chiave per ogni elemento nel nostro array.
Quindi, quando React aggiorna un array di elementi, confronterà solo le chiavi degli elementi nel vecchio e nel nuovo array per determinare quali elementi sono stati aggiunti, rimossi o spostati. React eseguirà un confronto più dettagliato del contenuto degli elementi solo se le chiavi non corrispondono o se non ci sono chiavi specificate (il confronto iniziale in cui non avevamo chiavi).
Quindi, in un certo senso, React esegue ancora un confronto durante l'aggiornamento di un array di elementi, ma confrontando le chiavi anziché l'intero array, può ottimizzare il processo di aggiornamento e migliorare le prestazioni.
Il confronto con le chiavi è più veloce ed efficiente rispetto al confronto degli interi elementi, in quanto consente a React di determinare rapidamente quali elementi sono stati aggiunti, rimossi o spostati. Ciò aiuta a ridurre al minimo la quantità di lavoro che React deve svolgere durante gli aggiornamenti e garantisce che gli aggiornamenti vengano elaborati nel modo più efficiente possibile.
Perché non utilizzare l'indice come chiavi?
Il callback nella funzione array.map() accetta un parametro chiamato index, che dà accesso al valore di indice di ogni elemento. Possiamo impostare la chiave per l'indice del particolare elemento. Ma questo è un grande no!
function Component()
const cart = ["Laptop," "Headphones"];
return (
<div>
cart.map((eachItem, index) =>
return h1 key=index>eachItem/h1>;
})}
</div>
);
}
export default component;
React la pensa così: se il puntello chiave di un elemento non è cambiato, non ho bisogno di eseguire un controllo dettagliato sul contenuto di quell'elemento. Presumo che se la chiave non viene aggiornata, le cose sono le stesse.
Math.random() — NO!
Bene, potremmo pensare che usare Math.random() per le chiavi sia una buona idea, in quanto genererà un numero casuale che sarà unico tra tutte le chiavi in quell'array. Ma dobbiamo tenere presente che verrà generata una nuova chiave ad ogni rendering, anche se l'array stesso non è cambiato . Ciò può far sì che React presuma erroneamente che un elemento sia cambiato o sia stato aggiunto. Ciò vanifica lo scopo dell'utilizzo delle chiavi perché React non può confrontare accuratamente le chiavi tra i rendering per identificare quali elementi sono effettivamente cambiati.
Quindi, la regola è scegliere una chiave che sia stabile e coerente tra i rendering in modo che React possa confrontare accuratamente le chiavi tra i rendering per identificare quali elementi sono stati modificati, aggiunti o rimossi dall'array. Quindi - nessun indice, nessuna matematica. casuale() ❌