primo, essere chiaro il motivo per cui si utilizza key
...
Fornire un key
per ogni elemento in un elenco è utile quando tale elenco è abbastanza dinamica - quando nuove voci della lista vengono aggiunti e rimossi regolarmente, soprattutto se l'elenco è lungo e gli elementi vengono aggiunti/rimossi nella parte superiore dell'elenco.
keys
in grado di fornire grandi miglioramenti delle prestazioni, perché consentono a React di ridisegnare in modo più efficiente questi elenchi modificabili. O, più precisamente, consente a React di evitare di ridisegnare elementi che hanno la stessa chiave dell'ultima volta, e che non sono stati modificati, e che sono stati semplicemente mescolati in alto o in basso.
In secondo luogo, essere ciò che si dovrebbe fare chiaro se la lista è piuttosto statica (non cambia tutto il tempo) o se non v'è alcun valore univoco associato a ogni voce ...
Don usare il :key
affatto. Invece, utilizzare into
come questo:
(defn categorymanager []
(let [cats (re-frame/subscribe [:cats])]
(fn []
[:div
(into [:ul] (map #(vector :li (:text %)) @cats))])))
Avviso quanto è successo qui.L'elenco fornito da map
è piegato into
vettore [:ul]
. Alla fine, nessuna lista in vista. Solo vettori annidati.
Viene visualizzato solo un avviso relativo alla mancanza di chiavi quando si incorpora un errore list
. Sopra non è incluso lo list
, solo vectors
.
Terzo, se l'elenco è davvero dinamica ...
una possibilità unica key
a ciascun elemento (fratelli amoung unici). Nell'esempio riportato, il :text
è di per sé una buona abbastanza key
(suppongo che è unico):
(defn categorymanager []
(let [cats (re-frame/subscribe [:cats])]
(fn []
[:div
[:ul (map #(vector :li {:key (:text %)} (:text %)) @cats)]])))
Quello map
si tradurrà in un list
che è il primo parametro al [:ul]
. Quando Reagent/React vede che list
vorrà vedere keys
su ciascun elemento (ricorda che gli elenchi sono diversi dai vettori in singhiozzo di Reagent) e stamperà gli avvisi alla console che erano keys
mancanti.
Quindi è necessario aggiungere uno key
a ciascun articolo dello list
. Nel codice sopra non aggiungiamo :key
tramite metadati (sebbene tu possa farlo in questo modo se vuoi), e invece stiamo fornendo il key
tramite il 1 ° parametro (dello [:li]
), che normalmente contiene anche dati di stile.
Infine - parte 1 NON usare map-indexed
come suggerito in un'altra risposta.
key
deve essere un valore univoco associato a ciascun articolo. Allegare un intero arb non fa nulla di utile - beh, si sbarazza degli avvertimenti nella console, ma dovresti usare la tecnica into
qui sopra se è tutto ciò che vuoi.
Infine - parte 2 non v'è alcuna differenza tra map
e for
in questo contesto.
Entrambi producono un list
. Se questo list
ha le chiavi, allora nessun avvertimento. Ma se mancano le chiavi, allora molti avvertimenti. Ma come è stata creata la lista non ci entra.
Quindi, questa versione for
è praticamente la stessa della versione map
. Alcuni potrebbero preferire esso:
(defn categorymanager []
(let [cats (re-frame/subscribe [:cats])]
(fn []
[:div
[:ul (for [i @cats] [:li {:key (:text i)} (:text i)])]])))
che può anche essere scritta utilizzando i metadati come questo:
(defn categorymanager []
(let [cats (re-frame/subscribe [:cats])]
(fn []
[:div
[:ul (for [i @cats] ^{:key (:text i)}[:li (:text i)])]])))
Infine - parte 3
mapv
è un problema a causa di questo problema: https://github.com/Day8/re-frame/wiki/Using-%5Bsquare-brackets%5D-instead-of-%28parentheses%29#appendix-2
Perle dal creatore del re-frame! Grazie!!! –
In reddit la tua risposta è stata descritta come epica. :-) –