Menulis API untuk komponen Bereaksi, bagian 3: urutan alat peraga penting

Menulis API untuk komponen Bereaksi, bagian 1: jangan membuat alat peraga yang bertentangan

Menulis API untuk Komponen Bereaksi, Bagian 2: Beri Nama untuk Perilaku, Bukan Interaksi

Menulis API untuk komponen Bereaksi, bagian 3: urutan alat peraga penting

Menulis API untuk Komponen Bereaksi, Bagian 4: Waspadai Apropacalypse!

Menulis API untuk Komponen Bereaksi, Bagian 5: Cukup Gunakan Komposisi

Kami menulis API untuk komponen Bereaksi, bagian 6: kami membuat komunikasi antar komponen

Mari kita mulai dengan komponen Bereaksi sederhana yang menampilkan tag jangkar:


tautan


<Link href="sid.studio">Click me</Link> //   : <a href="sid.studio" class="link">Click me</a> 

Seperti apa bentuk kode komponen:


 const Link = props => { return ( <a href={props.href} className="link"> {props.children} </a> ) } 

Kami juga ingin dapat menambahkan atribut html ke elemen, seperti id , target , title , data-attr , dll.


Karena ada banyak atribut HTML, kita bisa meneruskan semua alat peraga dan menambahkan yang kita butuhkan (seperti className )


(Catatan: Anda tidak boleh melewatkan atribut yang Anda buat untuk komponen ini yang tidak ada dalam spesifikasi HTML)


Dalam hal ini, Anda cukup menggunakan className


 const Link = props => { /*    (spread ),     ( ) */ return <a {...props} className="link" /> } 

Di situlah menjadi menarik.


Segalanya tampak baik-baik saja ketika seseorang melewati id atau target :


 <Link href="sid.studio" id="my-link">Click me</Link> //   : <a href="sid.studio" id="my-link" class="link">Click me</a> 

tetapi apa yang terjadi ketika seseorang melewati className ?


tautan


 <Link href="sid.studio" className="red-link">Click me</Link> //   : <a href="sid.studio" class="link">Click me</a> 

Yah, tidak ada yang terjadi. Bereaksi sepenuhnya mengabaikan kelas khusus. Mari kita kembali ke fungsinya:


 const Link = props => { return <a {...props} className="link" /> } 

Oke, mari kita bayangkan bagaimana ini ...props mengkompilasi, kode di atas setara dengan ini:


 const Link = props => { return ( <a href="sid.studio" className="red-link" className="link" > Click me </a> ) } 

Lihat konfliknya? Ada dua className . Bagaimana Bereaksi menangani ini?


Yah, Bereaksi tidak melakukan apa-apa. Babel melakukannya!


Ingat bahwa JSX "menghasilkan" React.createElement . Alat peraga dikonversi ke objek dan diteruskan sebagai argumen. Objek tidak mendukung kunci duplikat, sehingga className kedua akan menimpa yang pertama.


 const Link = props => { return React.createElement( 'a', { className: 'link', href: 'sid.studio' }, 'Click me' ) } 



Oke, sekarang kita sudah tahu tentang masalahnya, bagaimana kita bisa menyelesaikannya?


Sangat berguna untuk memahami bahwa kesalahan ini terjadi karena konflik nama, dan ini bisa terjadi dengan prop apa pun, dan bukan hanya dengan className . Jadi keputusan tergantung pada perilaku yang ingin Anda terapkan.


Ada tiga skenario yang mungkin:


  1. Pengembang yang menggunakan komponen kami harus dapat mengganti nilai prop standar.
  2. Kami tidak ingin membiarkan pengembang mengubah beberapa alat peraga
  3. Pengembang harus dapat menambahkan nilai sambil mempertahankan nilai default.

Mari kita pisahkan mereka satu per satu.


1. Pengembang yang menggunakan komponen kami harus dapat mengganti nilai prop standar


Ini adalah perilaku yang biasanya Anda harapkan dari atribut lain - id , title , dll.


Kita sering melihat pengaturan test id dalam kosmos (sistem desain yang saya kerjakan). Setiap komponen menerima data-test-id default, kadang-kadang pengembang ingin menambahkan pengidentifikasi tes mereka sendiri, untuk menunjukkan penggunaan spesifik.


Berikut ini adalah salah satu contoh penggunaan:


remah roti


 const Breadcrumb = () => ( <div className="breadcrumb" data-test-id="breadcrumb"> <Link data-test-id="breadcrumb.link">Home</Link> <Link data-test-id="breadcrumb.link">Parent</Link> <Link data-test-id="breadcrumb.link">Page</Link> </div> ) 

Breadcrumb menggunakan tautan, tetapi Anda ingin dapat menggunakannya dalam pengujian dengan data-test-id lebih spesifik. Ada cacat di dalamnya.


Dalam kebanyakan kasus, alat peraga khusus harus diutamakan daripada alat peraga standar.


Dalam praktiknya, ini berarti bahwa props default harus terlebih dahulu, dan kemudian {...props} untuk menimpanya.


 const Link = props => { return ( <a className="link" data-test-id="link" {...props} /> ) } 

Ingat bahwa tampilan data-test-id (dari props) akan menggantikan yang pertama (secara default). Oleh karena itu, ketika seorang pengembang melampirkan data-test-id atau className data-test-id nya sendiri, ia menimpa yang sebelumnya:


 1. <Link href="sid.studio">Click me</Link> 2. <Link href="sid.studio" data-test-id="breadcrumb.link">Click me</Link> //   : 1. <a class="link" href="sid.studio" data-test-id="link">Click me</a> 2. <a class="link" href="sid.studio" data-test-id="breadcrumb.link">Click me</a> 

Kita dapat melakukan hal yang sama dengan className :


tautan merah


 <Link href="sid.studio" className="red-link">Click me</Link> //   : <a href="sid.studio" class="red-link" data-test-id="link">Click me</a> 

Ini terlihat agak aneh, saya tidak yakin kita harus membiarkan ini! Mari kita bicarakan ini lebih lanjut.


2. Kami tidak ingin mengizinkan pengembang untuk mengubah beberapa alat peraga


Misalkan kita tidak ingin pengembang mengubah tampilan (via className ), tetapi kami tidak keberatan mereka mengubah alat peraga lain, seperti id , data-test-id , dll.


Kita dapat melakukan ini dengan memesan urutan atribut kita:


 const Link = props => { return ( <a data-test-id="link" {...props} className="link" /> ) } 

Ingat bahwa atribut di sebelah kanan akan menimpa atribut di sebelah kiri. Dengan demikian, segala sesuatu sebelum {...props} dapat didefinisikan ulang, tetapi semua yang sesudahnya tidak dapat didefinisikan ulang.


Untuk menyederhanakan pekerjaan pengembang, Anda bisa menampilkan peringatan bahwa Anda tidak bisa menentukan className Anda.


Saya ingin membuat alat peraga tipe saya sendiri untuk ini:


 Link.PropTypes = { className: function(props) { if (props.className) { return new Error( `  className  Link,      ` ) } } } 

Saya punya video yang membahas tentang memeriksa jenis alat peraga khusus , jika Anda tertarik untuk menulisnya.


Sekarang, ketika pengembang mencoba menimpa className , ini tidak akan berfungsi, dan pengembang akan menerima peringatan.


tautan


 <Link href="sid.studio" className="red-link">Click me</Link> //   : <a href="sid.studio" class="link">Click me</a> 

 :   :   className  Link,       

Jujur, saya harus menggunakan template ini hanya sekali atau dua kali. Biasanya Anda mempercayai pengembang menggunakan komponen Anda.


Yang membawa kita untuk berbagi.


3. Pengembang harus dapat menambahkan nilai sambil mempertahankan nilai default


Ini mungkin kasus penggunaan yang paling umum untuk kelas.


tautan


 <Link href="sid.studio" className="underline">Click me</Link> //   : <a href="sid.studio" class="link underline">Click me</a> 

Implementasinya terlihat seperti ini:


 const Link = props => { /*  className   */ const { className, otherProps } = props /*     */ const classes = 'link ' + className return ( <a data-test-id="link" className={classes} {...otherProps} /*     */ /> ) } 

Templat ini juga berguna untuk menerima penangan acara (misalnya, onClick ) untuk komponen yang sudah memilikinya.


beralih


 <Switch onClick={value => console.log(value)} /> 

Beginilah implementasi dari komponen ini:


 class Switch extends React.Component { state = { enabled: false } onToggle = event => { /*      */ this.setState({ enabled: !this.state.enabled }) /*       */ if (typeof this.props.onClick === 'function') { this.props.onClick(event, this.state.enabled) } } render() { /*        ️ */ return <div class="toggler" onClick={this.onToggle} /> } } 

Ada cara lain untuk menghindari bentrokan nama di penangan acara, saya menggambarkannya di API Menulis untuk Komponen Bereaksi, Bagian 2: Berikan nama untuk perilaku, bukan cara interaksi .




Untuk setiap skenario, Anda dapat menggunakan pendekatan berbeda.


  1. Sebagian besar waktu: Pengembang harus dapat mengubah nilai prop, nilai yang ditetapkan secara default
  2. Biasanya untuk penata gaya dan acara: Pengembang harus dapat menambahkan nilai di atas nilai default
  3. Kasus yang jarang terjadi ketika Anda perlu membatasi tindakan pengembang: Pengembang tidak diizinkan untuk mengubah perilaku, Anda perlu mengabaikan nilai-nilainya dan, pada saat yang sama, menampilkan peringatan

Source: https://habr.com/ru/post/id459380/


All Articles