Kako reagiraju tipke i zabavne stvari koje s njima možete raditi

React koristi keyatribut 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 indexkao ključ. Ali što točno može poći po zlu kada se keys koristi na loš način? Što još možemo učiniti kad se igramo tipkama?

Za bolje razumijevanje, razmotrimo primjer prikazivanja popisa inputs. Klikom na gumb umetnut ćemo novu stavku s tekstom Frontna 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 indexkao 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 Items tekstom Secondumjesto ? Evo što se događa:Front

    1. Item is an uncontrolled component: Tekst koji korisnik upiše u svoje inputpolje pohranjuje se kaostate
    2. Nova stavka podataka { text: "Front" }umetnuta je na početak podataka s popisa.
    3. Popis se ponovno prikazuje s vrijednošću indeksa kao key. Dakle, prethodne se komponente ponovno koriste za prve dvije stavke podataka i dobivaju ispravne rekvizite Fronti First, ali stanje se ne ažurira u Item. Zato prve dvije komponente sadrže isti tekst.
    4. Stvorena je nova instanca komponente za key: 2jer nije pronađen prethodni odgovarajući ključ. Ispunjava propsse zadnja stavka podataka s popisa koja je Second.

    Još jedna zanimljiva točka su renderpozivi koji se događaju. Stavka je a PureComponent, pa se ažurira samo kada se promijeni textoslonac (ili stanje):

    rerendering Frontrerendering Firstrerendering SecondMounted Second

    Sve su komponente ponovno prikazane. To se događa jer se element s key: 0ponovno koristi za prvu podatkovnu stavku i prima je props, ali prva podatkovna stavka sada je novi Frontobjekt 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 idjednokratnu izradu (ne na svakom prikazivanju!). Sve instance komponenata bit će podudarne s odgovarajućom stavkom podataka. Primaju isto propskao i prije, a ovo izbjegava drugo render.

    Zanemarimo zasad prednosti izvedbe koje dolazi od upotrebe ids 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 Itemkao 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 keys 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/ componentWillReceivePropsnije implementirano da odražava ponovljene propspromjene u njegovom unutarnjem stanju) , standardni React toolbox vam ne može pomoći ovdje. Ne postoji forceRemount.

    Međutim, možemo samo postaviti novo keyna ovu komponentu kako bismo postigli željeno ponašanje potpune inicijalizacije nove komponente. Stara komponenta će se demontirati, a nova će se montirati s novom propsinicijalizacijom state.

    TL; DR:

    Korištenje indexkao ključa može:

    1. dovesti do nepotrebnih ponovnih prikaza
    2. uvesti greške kad su stavke popisa nekontrolirane komponente, ali se i dalje koristeprops

    keySvojstvo se može koristiti na snagu kompletan remont komponente, što ponekad može biti koristan.

    Izvorno objavljeno na cmichel.io