
React koristi key
atribut tijekom faze pomirenja da odluči koji se elementi mogu ponovno koristiti za sljedeći prikaz. Važni su za dinamičke popise. React će usporediti ključeve novog elementa s prethodnim ključevima i 1) montirati komponente s novim ključem 2) demontirati komponente čiji se ključevi više ne koriste.
Mnogi programeri React-a čuli su općeniti savjet koji ne biste trebali koristiti index
kao ključ. Ali što točno može poći po zlu kada se key
s koristi na loš način? Što još možemo učiniti kad se igramo tipkama?
Za bolje razumijevanje, razmotrimo primjer prikazivanja popisa input
s. Klikom na gumb umetnut ćemo novu stavku s tekstom Front
na početak popisa.
import React from "react";import { render } from "react-dom";class Item extends React.PureComponent { state = { text: this.props.text }; onChange = event => { this.setState({ text: event.target.value }); }; componentDidMount() { console.log("Mounted ", this.props.text); } componentWillUnmount() { console.log("Unmounting ", this.props.text); } render() { console.log("rerendering ", this.props.text); const { text } = this.state; return ( ); }}class App extends React.Component { state = { items: [ { text: "First", id: 1 }, { text: "Second", id: 2 } ] }; addItem = () => { const items = [{ text: "Front", id: Date.now() }, ...this.state.items]; this.setState({ items }); }; render() { return (
{this.state.items.map((item, index) => ( ))}
Add Item ); }}render(, document.getElementById("root"));
Ako koristite index
kao ključ, događa se sljedeće:
CodeSandbox
CodeSandbox je mrežni uređivač prilagođen web aplikacijama. codeandbox.io

Što ako se na stražnjem dijelu popisa umetne drugi Item
s tekstom Second
umjesto ? Evo što se događa:Front
Item is an uncontrolled component
: Tekst koji korisnik upiše u svojeinput
polje pohranjuje se kaostate
- Nova stavka podataka
{ text: "Front" }
umetnuta je na početak podataka s popisa. - Popis se ponovno prikazuje s vrijednošću indeksa kao
key
. Dakle, prethodne se komponente ponovno koriste za prve dvije stavke podataka i dobivaju ispravne rekviziteFront
iFirst
, ali stanje se ne ažurira uItem
. Zato prve dvije komponente sadrže isti tekst. - Stvorena je nova instanca komponente za
key: 2
jer nije pronađen prethodni odgovarajući ključ. Ispunjavaprops
se zadnja stavka podataka s popisa koja jeSecond
.

Još jedna zanimljiva točka su render
pozivi koji se događaju. Stavka je a PureComponent
, pa se ažurira samo kada se promijeni text
oslonac (ili stanje):
rerendering Frontrerendering Firstrerendering SecondMounted Second
Sve su komponente ponovno prikazane. To se događa jer se element s key: 0
ponovno koristi za prvu podatkovnu stavku i prima je props
, ali prva podatkovna stavka sada je novi Front
objekt koji pokreće render
. Isto se događa s ostalim komponentama, jer su stare stavke podataka sada pomaknute za jedno mjesto.
Pa, u čemu je popravak? Popravak je jednostavan: svakoj stavci podataka s popisa dajemo jedinstvenu id
jednokratnu izradu (ne na svakom prikazivanju!). Sve instance komponenata bit će podudarne s odgovarajućom stavkom podataka. Primaju isto props
kao i prije, a ovo izbjegava drugo render
.
Zanemarimo zasad prednosti izvedbe koje dolazi od upotrebe id
s na dinamičkim popisima. Primjer pokazuje da se greške koje unose ključevi događaju samo u vezi s nekontroliranim komponentama , komponentama koje zadržavaju unutarnje stanje .
Ako prepišemo Item
kao kontroliranu komponentu, premještanjem stanja iz nje, pogreška više nema.
Zašto? Opet, jer je bug ponovno koristio komponentu za drugu stavku podataka. Stoga je unutarnje stanje i dalje odražavalo stanje prethodne stavke podataka , ali rekviziti druge . Čineći komponentu kontroliranom, uklanjanjem njezinog stanja u potpunosti, više nemamo ove razlike. (Ali još uvijek postoji problem s nepotrebnim ponovnim prikazivanjem.)
Zlouporaba tipki za popravljanje pokvarenih komponenata treće strane
React treba samo key
s kada se podudara nekoliko elemenata, tako da postavljanje ključa za jedno dijete nije potrebno. No, još uvijek može biti korisno postaviti ključ na jednu podređenu komponentu.
Ako promijenite ključ, React će baciti cijelu komponentu (demontirati je) i na njezino mjesto montirati novu instancu komponente. Zašto bi ovo moglo biti korisno?
Opet se vraćamo nekontroliranim komponentama . Ponekad upotrebljavate komponentu treće strane i ne možete izmijeniti njezin kôd da bi bio pod nadzorom. Ako komponenta ima neko unutarnje stanje i ono je implementirano na loš način (na primjer, stanje je izvedeno samo jednom u konstruktoru, ali getDerivedStateFromProps
/ componentWillReceiveProps
nije implementirano da odražava ponovljene props
promjene u njegovom unutarnjem stanju) , standardni React toolbox vam ne može pomoći ovdje. Ne postoji forceRemount
.
Međutim, možemo samo postaviti novo key
na ovu komponentu kako bismo postigli željeno ponašanje potpune inicijalizacije nove komponente. Stara komponenta će se demontirati, a nova će se montirati s novom props
inicijalizacijom state
.
TL; DR:
Korištenje index
kao ključa može:
- dovesti do nepotrebnih ponovnih prikaza
- uvesti greške kad su stavke popisa nekontrolirane komponente, ali se i dalje koriste
props
key
Svojstvo se može koristiti na snagu kompletan remont komponente, što ponekad može biti koristan.
Izvorno objavljeno na cmichel.io
