Cara kerja tombol React dan hal menyenangkan yang dapat Anda lakukan dengannya

React menggunakan keyatribut tersebut selama fase rekonsiliasi untuk memutuskan elemen mana yang dapat digunakan kembali untuk render berikutnya. Mereka penting untuk daftar dinamis. React akan membandingkan kunci dari elemen baru dengan kunci sebelumnya dan 1) memasang komponen yang memiliki kunci baru 2) melepas komponen yang kuncinya tidak digunakan lagi.

Banyak pengembang React telah mendengar saran umum yang sebaiknya tidak Anda gunakan indexsebagai kunci. Tapi apa sebenarnya yang bisa salah saat menggunakan keys dengan cara yang buruk? Apa lagi yang bisa kita lakukan saat kita bermain-main dengan kunci?

Untuk pemahaman yang lebih baik, mari pertimbangkan contoh merender daftar inputs. Saat mengklik tombol, kami akan memasukkan item baru dengan teks Frontke depan daftar.

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"));

    Jika Anda menggunakan indexsebagai kunci, hal berikut akan terjadi:

    CodeSandbox

    CodeSandbox adalah editor online yang disesuaikan untuk aplikasi web. codesandbox.io

    Bagaimana jika yang lain Itemdengan teks Secondbukannya Frontdisisipkan di belakang daftar? Inilah yang terjadi:

    1. Item is an uncontrolled component: Teks yang ditulis pengguna ke dalam inputbidangnya disimpan sebagaistate
    2. Item data baru { text: "Front" }dimasukkan ke awal data daftar.
    3. Daftar dirender ulang dengan nilai indeks sebagai key. Jadi komponen sebelumnya digunakan kembali untuk dua item data pertama dan diberi props yang benar Frontdan First, tetapi statusnya tidak diperbarui di Item. Itulah mengapa dua contoh komponen pertama menyimpan teks yang sama.
    4. Instance komponen baru dibuat key: 2karena tidak ada kunci yang cocok sebelumnya yang ditemukan. Diisi dengan item data daftarprops terakhir yaitu .Second

    Hal menarik lainnya adalah renderpanggilan yang terjadi. Item adalah a PureComponent, jadi hanya diperbarui ketika textprop (atau status) berubah:

    rerendering Frontrerendering Firstrerendering SecondMounted Second

    Semua komponen dirender ulang. Ini terjadi karena elemen dengan key: 0digunakan kembali untuk item data pertama dan menerimanya props, tetapi item data pertama sekarang menjadi Frontobjek baru , memicu a render. Hal yang sama terjadi pada komponen lainnya, karena item data lama sekarang semuanya digeser oleh satu tempat.

    Jadi apa perbaikannya? Perbaikannya mudah: kami memberikan setiap item data daftar idsatu kali unik setelah pembuatan (bukan pada setiap render!). Semua contoh komponen akan dicocokkan dengan item data yang sesuai. Mereka menerima yang sama propsseperti sebelumnya, dan ini menghindari yang lain render.

    Mari kita abaikan manfaat kinerja yang datang dari penggunaan ids dalam daftar dinamis untuk saat ini. Contoh tersebut menunjukkan bahwa bug yang diperkenalkan oleh kunci hanya pernah terjadi terkait dengan komponen yang tidak terkontrol , komponen yang mempertahankan status internal .

    Jika kita menulis ulang Itemsebagai komponen terkontrol, dengan mengeluarkan status darinya, bug akan hilang.

    Mengapa? Sekali lagi, karena bug itu menggunakan kembali komponen untuk item data yang berbeda. Oleh karena itu, status internal masih mencerminkan status item data sebelumnya , tetapi props dari item data yang berbeda . Membuat komponen dikontrol, dengan menghapus statusnya sepenuhnya, kami tidak lagi memiliki perbedaan ini. (Tapi masih ada masalah dengan render ulang yang tidak perlu.)

    Menyalahgunakan kunci untuk memperbaiki komponen pihak ketiga yang rusak

    React hanya membutuhkan keys saat mencocokkan beberapa elemen, jadi menyetel kunci pada satu anak tidak diperlukan. Tapi tetap berguna untuk menyetel kunci pada satu komponen anak.

    Jika Anda mengubah kunci, React akan membuang seluruh komponen (melepasnya), dan memasang instance komponen baru di tempatnya. Mengapa ini bisa berguna?

    Sekali lagi, kami kembali ke komponen yang tidak terkontrol . Terkadang, Anda menggunakan komponen pihak ketiga dan Anda tidak dapat mengubah kodenya untuk membuatnya terkontrol. Jika sebuah komponen memiliki beberapa keadaan internal dan itu diimplementasikan dengan cara yang buruk (misalnya, keadaan diturunkan hanya sekali dalam konstruktor, tetapi getDerivedStateFromProps/ componentWillReceivePropstidak diimplementasikan untuk mencerminkan propsperubahan yang berulang dalam keadaan internalnya) , kotak alat React standar tidak dapat membantu Anda sini. Tidak ada forceRemount.

    Namun, kita hanya dapat menetapkan yang baru keypada komponen ini untuk mencapai perilaku yang diinginkan dalam menginisialisasi komponen baru sepenuhnya. Komponen lama akan dilepas, dan yang baru akan dipasang dengan propsinisialisasi baru state.

    TL; DR:

    Menggunakan indexsebagai kunci dapat:

    1. menyebabkan perenderan ulang yang tidak perlu
    2. memperkenalkan bug ketika item daftar merupakan komponen yang tidak terkontrol tetapi masih digunakanprops

    The keyproperti dapat digunakan untuk memaksa remount lengkap komponen, yang kadang-kadang dapat berguna.

    Awalnya diterbitkan di cmichel.io