Buduję komponent React, który akceptuje źródło danych JSON i tworzy sortowalną tabelę.
Każdy z wierszy danych dynamicznych ma przypisany unikalny klucz, ale wciąż pojawia się błąd:
Każde dziecko w tablicy powinno mieć unikalny „klucz” rekwizyt.
Sprawdź metodę renderowania TableComponent.
Moja TableComponent
metoda renderowania zwraca:
<table>
<thead key="thead">
<TableHeader columns={columnNames}/>
</thead>
<tbody key="tbody">
{ rows }
</tbody>
</table>
TableHeader
Składnikiem jest jednorzędowe i również posiada unikalny klucz przypisany do niego.
Każdy row
w rows
zbudowany jest ze składnika z unikalnym kluczem:
<TableRowItem key={item.id} data={item} columns={columnNames}/>
I TableRowItem
wygląda to tak:
var TableRowItem = React.createClass({
render: function() {
var td = function() {
return this.props.columns.map(function(c) {
return <td key={this.props.data[c]}>{this.props.data[c]}</td>;
}, this);
}.bind(this);
return (
<tr>{ td(this.props.item) }</tr>
)
}
});
Co powoduje unikalny błąd klucza prop?
javascript
reactjs
Brett DeWoody
źródło
źródło
key
właściwość. Pomoże ReactJS znaleźć odniesienia do odpowiednich węzłów DOM i zaktualizować tylko zawartość wewnątrz narzutów, ale nie zrenderuje całej tabeli / wiersza.rows
tablicę, a najlepiej jsfiddle? Dont potrzebująkey
nieruchomości nathead
itbody
na drodze.Odpowiedzi:
Powinieneś dodać klucz do każdego dziecka, a także do każdego elementu wewnątrz dzieci .
W ten sposób React może obsłużyć minimalną zmianę DOM.
W twoim kodzie każde z nich
<TableRowItem key={item.id} data={item} columns={columnNames}/>
próbuje wyrenderować niektóre dzieci bez klucza.Sprawdź ten przykład .
Spróbuj usunąć element
key={i}
z<b></b>
elementu div (i sprawdź konsolę).W przykładzie, jeśli nie damy klucza do
<b>
elementu i chcemy zaktualizować tylko ten elementobject.city
, React musi ponownie renderować cały wiersz względem samego elementu.Oto kod:
Odpowiedź wysłana przez @Chris na dole jest o wiele bardziej szczegółowa niż ta odpowiedź. Proszę spojrzeć na https://stackoverflow.com/a/43892905/2325522
Reaguj dokumentację dotyczącą znaczenia kluczy w uzgodnieniu: Klucze
źródło
key
wartość rekwizytu jest unikalna dla każdego elementu i umieszczaszkey
rekwizyt w komponencie, który jest najbliżej granic tablicy. Na przykład w React Native najpierw próbowałem umieścićkey
rekwizyt w<Text>
komponencie. Musiałem jednak umieścić go w<View>
elemencie macierzystym<Text>
. jeśli Array == [(Widok> Tekst), (Widok> Tekst)], musisz ustawić go w widoku. Nie tekst.Zachowaj ostrożność podczas iteracji po tablicach !!
Jest powszechnym błędnym przekonaniem, że użycie indeksu elementu w tablicy jest akceptowalnym sposobem tłumienia błędu, który prawdopodobnie znasz:
Jednak w wielu przypadkach tak nie jest! Jest to anty-wzór, który w niektórych sytuacjach może prowadzić do niepożądanych zachowań .
Zrozumienie
key
propReact używa
key
rekwizytu, aby zrozumieć relację elementu do elementu DOM, która jest następnie wykorzystywana w procesie uzgadniania . Dlatego bardzo ważne jest, aby klucz zawsze pozostawał unikalny , w przeciwnym razie istnieje duża szansa, że React pomieszać elementy i zmutować niewłaściwy. Ważne jest również, aby te klucze pozostały statyczne podczas wszystkich renderowań w celu zachowania najlepszej wydajności.Biorąc to pod uwagę, nie zawsze trzeba stosować powyższe, pod warunkiem, że wiadomo, że tablica jest całkowicie statyczna. Jednak w miarę możliwości zaleca się stosowanie najlepszych praktyk.
Deweloper React powiedział w tym numerze GitHub :
Krótko mówiąc,
key
powinno być:Korzystanie z
key
propZgodnie z powyższym wyjaśnieniem dokładnie przestudiuj poniższe próbki i spróbuj wdrożyć, w miarę możliwości, zalecane podejście.
Źle (potencjalnie)
Jest to prawdopodobnie najczęstszy błąd występujący podczas iteracji nad tablicą w React. Takie podejście nie jest technicznie „złe” , jest po prostu… „niebezpieczne”, jeśli nie wiesz, co robisz. Jeśli iterujesz przez tablicę statyczną, jest to całkowicie poprawne podejście (np. Tablica linków w menu nawigacyjnym). Jeśli jednak dodajesz, usuwasz, zmieniasz kolejność lub filtrujesz elementy, musisz zachować ostrożność. Spójrz na to szczegółowe wyjaśnienie w oficjalnej dokumentacji.
Pokaż fragment kodu
W tym fragmencie używamy niestatycznej tablicy i nie ograniczamy się do używania go jako stosu. To niebezpieczne podejście (zobaczysz dlaczego). Zauważ, jak dodając elementy na początku tablicy (w zasadzie cofnij przesunięcie), wartość każdego z nich
<input>
pozostaje na miejscu. Dlaczego? Ponieważkey
nie jednoznacznie identyfikuje każdy element.Innymi słowy, na początku
Item 1
makey={0}
. Kiedy dodamy drugi element, najwyższy element staje sięItem 2
, a następnieItem 1
jako drugi element. Jednak terazItem 1
makey={1}
ikey={0}
już nie ma. Zamiast tegoItem 2
teraz makey={0}
!!React uważa, że
<input>
elementy się nie zmieniły, ponieważItem
klawisz z0
jest zawsze na górze!Dlaczego więc takie podejście jest czasami złe?
Takie podejście jest ryzykowne tylko wtedy, gdy tablica jest w jakiś sposób filtrowana, przestawiana lub elementy są dodawane / usuwane. Jeśli zawsze jest statyczny, to jest całkowicie bezpieczny w użyciu. Na przykład menu nawigacyjne, takie jak,
["Home", "Products", "Contact us"]
może być bezpiecznie iterowane za pomocą tej metody, ponieważ prawdopodobnie nigdy nie dodasz nowych łączy ani nie zmienisz ich położenia.W skrócie, oto kiedy możesz bezpiecznie używać indeksu jako
key
:Gdybyśmy zamiast tego we fragmencie powyżej przesunęli dodany element na koniec tablicy, kolejność dla każdego istniejącego elementu zawsze byłaby poprawna.
Bardzo źle
Chociaż takie podejście prawdopodobnie zagwarantuje unikalność kluczy, zawsze wymusi reakcję w celu ponownego renderowania każdego elementu na liście, nawet jeśli nie jest to wymagane. To bardzo złe rozwiązanie, ponieważ ma duży wpływ na wydajność. Nie wspominając już o tym, że nie można wykluczyć możliwości kolizji klucza w przypadku,
Math.random()
gdy dwukrotnie otrzyma ten sam numer.Bardzo dobre
Jest to prawdopodobnie najlepsze podejście, ponieważ wykorzystuje właściwość, która jest unikalna dla każdego elementu w zestawie danych. Na przykład, jeśli
rows
zawiera dane pobrane z bazy danych, można użyć klucza podstawowego tabeli ( który zwykle jest liczbą automatycznie zwiększającą wartość ).Dobrze
To również dobre podejście. Jeśli zestaw danych nie zawiera żadnych danych gwarantujących unikalność ( np. Tablicę dowolnych liczb ), istnieje ryzyko kolizji klucza. W takich przypadkach najlepiej jest ręcznie wygenerować unikalny identyfikator dla każdego elementu w zestawie danych przed iteracją. Najlepiej podczas montowania komponentu lub odbierania zestawu danych ( np. Z
props
lub z wywołania asynchronicznego interfejsu API ), aby zrobić to tylko raz , a nie za każdym razem, gdy komponent jest ponownie renderowany. Istnieje już kilka bibliotek, które mogą dostarczyć takie klucze. Oto jeden przykład: indeks klucza reakcji .źródło
toString()
do konwersji na ciąg zamiast pozostawić jako liczbę. Czy to ważne, aby pamiętać?key
. Nie jestem pewien, dlaczego to konwertują.key
zawsze kończy się to ciągiem.To może komuś pomóc, ale może to być szybkie odniesienie. Jest to również podobne do wszystkich odpowiedzi przedstawionych powyżej.
Mam wiele lokalizacji, które generują listę przy użyciu poniższej struktury:
Po krótkiej próbie i błędzie (i niektórych frustracjach) dodanie właściwości klucza do najbardziej zewnętrznego bloku rozwiązało to. Zauważ też, że tag <> jest teraz zastąpiony tagiem teraz.
Oczywiście naiwnie używam indeksu iteracji (indeksu), aby wypełnić kluczową wartość w powyższym przykładzie. Idealnie byłoby użyć czegoś, co jest unikalne dla elementu listy.
źródło
Ostrzeżenie: każde dziecko w tablicy lub iteratorze powinno mieć unikalny „klucz” prop.
To ostrzeżenie, ponieważ dla elementów tablicy, nad którymi będziemy się powtarzać, będzie potrzebne unikalne podobieństwo.
React obsługuje iteracyjne renderowanie komponentów jako tablice.
Lepszym sposobem na rozwiązanie tego problemu jest zapewnienie indeksu elementów tablicy, które będą iterowane. Na przykład:
indeks jest React wbudowane rekwizyty.
źródło
Po prostu dodaj unikalny klucz do swoich komponentów
źródło
Sprawdź: klucz = undef !!!
Otrzymałeś również wiadomość ostrzegającą:
jeśli kod jest kompletny, ale jeśli jest włączony
someValue jest niezdefiniowany !!! Najpierw sprawdź to. Możesz zaoszczędzić godziny.
źródło
Najlepsze rozwiązanie zdefiniowania unikalnego klucza w reakcji: w mapie zainicjowałeś nazwę posta, następnie klucz zdefiniuj kluczem {post.id} lub w moim kodzie widzisz definiuję element nazwy, a następnie definiuję klucz według klucza = {item.id }:
źródło
To ostrzeżenie, ale rozwiązanie tego problemu sprawi, że reakcje będą znacznie SZYBSZE ,
Jest tak, ponieważ
React
musi jednoznacznie identyfikować każdą pozycję na liście. Powiedzmy, że jeśli stan elementu z tej listy zmienia się w Reactach,Virtual DOM
to React musi dowiedzieć się, który element został zmieniony i gdzie w DOM musi się zmienić, aby DOM przeglądarki był zsynchronizowany z DOMem Reactów wirtualnym.Jako rozwiązanie wystarczy wprowadzić
key
atrybut do każdegoli
tagu. Tokey
powinno być unikalną wartość dla każdego elementu.źródło
key
rekwizyt. Jeśli go nie podasz, React przypisze je automatycznie (aktualny indeks iteracji).key={i}
. To zależy od danych, które zawiera tablica. Na przykład, jeśli masz listę["Volvo", "Tesla"]
, to oczywiście Volvo jest identyfikowane przez klucz,0
a Tesla z1
- ponieważ jest to kolejność, w jakiej pojawią się w pętli. Teraz, jeśli zmienisz kolejność tablicy, klucze zostaną zamienione. W przypadku React, ponieważ „obiekt”0
wciąż znajduje się na górze, zinterpretuje tę zmianę raczej jako „zmianę nazwy”, a nie zmianę kolejności. Odpowiednie klawisze tu musiałby być w porządku,1
wtedy0
. Nie zawsze zmieniasz kolejność w trakcie działania, ale kiedy to robisz, jest to ryzyko.To rozwiąże problem.
źródło
Natrafiłem na ten komunikat o błędzie, ponieważ w
<></>
zamian za niektóre elementy w tablicynull
trzeba było zwrócić.źródło
Naprawiłem to za pomocą Guid dla każdego takiego klucza: Generowanie Guid:
A następnie przypisując tę wartość do znaczników:
źródło
Zasadniczo nie należy używać indeksu tablicy jako unikalnego klucza. Raczej można użyć
setTimeout(() => Date.now(),0)
, aby ustawić unikalny klucz lub uniquid UUID lub w jakikolwiek inny sposób, który wygeneruje unikatowy identyfikator, ale nie indeks tablicy jako unikalnego identyfikatora.źródło