Di bagian terjemahan tutorial Bereaksi ini, kita akan berbicara tentang arsitektur aplikasi Bereaksi. Secara khusus, kita akan membahas pola Wadah / Komponen yang populer.

β
Bagian 1: ikhtisar kursus, alasan popularitas React, ReactDOM dan JSXβ
Bagian 2: komponen fungsionalβ
Bagian 3: file komponen, struktur proyekβ
Bagian 4: komponen induk dan anakβ
Bagian 5: mulai bekerja pada aplikasi TODO, dasar-dasar gayaβ
Bagian 6: tentang beberapa fitur kursus, JSX dan JavaScriptβ
Bagian 7: gaya inlineβ
Bagian 8: terus bekerja pada aplikasi TODO, terbiasa dengan sifat-sifat komponenβ
Bagian 9: properti komponenβ
Bagian 10: Workshop bekerja dengan properti komponen dan gayaβ
Bagian 11: pembuatan markup dinamis dan metode susunan petaβ
Bagian 12: lokakarya, pekerjaan tahap ketiga pada aplikasi TODOβ
Bagian 13: komponen berbasis kelasβ
Bagian 14: lokakarya tentang komponen berbasis kelas, status komponenβ
Bagian 15: bengkel kesehatan komponenβ
Bagian 16: tahap keempat dari pengerjaan aplikasi TODO, penanganan acaraβ
Bagian 17: tahap kelima bekerja pada aplikasi TODO, memodifikasi status komponenβ
Bagian 18: tahap keenam dari pengerjaan aplikasi TODOβ
Bagian 19: metode siklus hidup komponenBagian 20: pelajaran pertama dalam rendering bersyaratβ
Bagian 21: pelajaran kedua dan lokakarya tentang rendering bersyaratβ
Bagian 22: tahap ketujuh bekerja pada aplikasi TODO, mengunduh data dari sumber eksternalβ
Bagian 23: pelajaran pertama tentang bekerja dengan formulirβ
Bagian 24: Pelajaran Bentuk Keduaβ
Bagian 25: Workshop bekerja dengan formulirβ
Bagian 26: arsitektur aplikasi, pola Container / Komponenβ
Bagian 27: proyek kursusPelajaran 44. Arsitektur Aplikasi, Wadah / Pola Komponen
β
AsliTerkadang jumlah pekerjaan yang menjadi tanggung jawab komponen terpisah terlalu besar, komponen harus menyelesaikan terlalu banyak tugas. Menggunakan pola Container / Component memungkinkan Anda untuk memisahkan logika aplikasi dari logika pembentukan representasi visualnya. Ini memungkinkan Anda untuk meningkatkan struktur aplikasi, untuk berbagi tanggung jawab atas kinerja berbagai tugas di antara berbagai komponen.
Pada pelajaran praktis sebelumnya, kami menciptakan komponen besar yang panjang kodenya mendekati 150 baris. Berikut adalah kode yang kami dapatkan:
import React, {Component} from "react" class App extends Component { constructor() { super() this.state = { firstName: "", lastName: "", age: "", gender: "", destination: "", isVegan: false, isKosher: false, isLactoseFree: false } this.handleChange = this.handleChange.bind(this) } handleChange(event) { const {name, value, type, checked} = event.target type === "checkbox" ? this.setState({ [name]: checked }) : this.setState({ [name]: value }) } render() { return ( <main> <form> <input name="firstName" value={this.state.firstName} onChange={this.handleChange} placeholder="First Name" /> <br /> <input name="lastName" value={this.state.lastName} onChange={this.handleChange} placeholder="Last Name" /> <br /> <input name="age" value={this.state.age} onChange={this.handleChange} placeholder="Age" /> <br /> <label> <input type="radio" name="gender" value="male" checked={this.state.gender === "male"} onChange={this.handleChange} /> Male </label> <br /> <label> <input type="radio" name="gender" value="female" checked={this.state.gender === "female"} onChange={this.handleChange} /> Female </label> <br /> <select value={this.state.destination} name="destination" onChange={this.handleChange} > <option value="">-- Please Choose a destination --</option> <option value="germany">Germany</option> <option value="norway">Norway</option> <option value="north pole">North Pole</option> <option value="south pole">South Pole</option> </select> <br /> <label> <input type="checkbox" name="isVegan" onChange={this.handleChange} checked={this.state.isVegan} /> Vegan? </label> <br /> <label> <input type="checkbox" name="isKosher" onChange={this.handleChange} checked={this.state.isKosher} /> Kosher? </label> <br /> <label> <input type="checkbox" name="isLactoseFree" onChange={this.handleChange} checked={this.state.isLactoseFree} /> Lactose Free? </label> <br /> <button>Submit</button> </form> <hr /> <h2><font color="#3AC1EF">Entered information:</font></h2> <p>Your name: {this.state.firstName} {this.state.lastName}</p> <p>Your age: {this.state.age}</p> <p>Your gender: {this.state.gender}</p> <p>Your destination: {this.state.destination}</p> <p>Your dietary restrictions:</p> <p>Vegan: {this.state.isVegan ? "Yes" : "No"}</p> <p>Kosher: {this.state.isKosher ? "Yes" : "No"}</p> <p>Lactose Free: {this.state.isLactoseFree ? "Yes" : "No"}</p> </main> ) } } export default App
Kelemahan pertama dari kode ini, yang langsung menarik perhatian Anda, adalah bahwa ketika bekerja dengannya, Anda harus terus menggulirnya di jendela editor.
Anda dapat melihat bahwa sebagian besar kode ini adalah logika pembentukan antarmuka aplikasi, isi dari metode
render()
. Selain itu, sejumlah kode bertanggung jawab untuk menginisialisasi keadaan komponen. Komponen ini juga memiliki apa yang disebut "logika bisnis" (yaitu, apa yang mengimplementasikan logika fungsi aplikasi). Ini adalah kode dari metode
handleChange()
.
Menurut hasil beberapa penelitian, diketahui bahwa kemampuan seorang programmer untuk memahami kode yang dia lihat sangat terganggu jika kode itu cukup panjang, dan programmer harus menggunakan scrolling untuk melihatnya secara keseluruhan. Saya memperhatikan hal ini selama kelas. Ketika kode yang saya bicarakan ternyata cukup panjang, dan saya harus terus menggulirnya, menjadi lebih sulit bagi siswa untuk melihatnya.
Alangkah baiknya jika kita mengerjakan ulang kode kita, berbagi tanggung jawab antara berbagai komponen untuk pembentukan antarmuka aplikasi (apa yang sekarang dijelaskan dalam metode
render()
) dan untuk implementasi logika aplikasi, yaitu, dengan definisi bagaimana seharusnya terlihat interface (kode yang sesuai sekarang diwakili oleh konstruktor dari komponen di mana negara diinisialisasi, dan
handleChange()
event
handleChange()
). Saat menggunakan pendekatan ini untuk desain aplikasi, kami, pada kenyataannya, bekerja dengan dua jenis komponen, dan harus dicatat bahwa Anda mungkin menemukan nama yang berbeda untuk komponen tersebut.
Kami akan menggunakan pola Wadah / Komponen di sini. Saat menggunakannya, aplikasi dibangun dengan membagi komponen menjadi dua jenis - ke dalam komponen wadah (kata Container merujuk pada namanya) dan komponen presentasi (ini adalah Komponen atas nama pola). Kadang-kadang komponen wadah disebut komponen "pintar", atau sekadar "wadah", dan komponen presentasi disebut komponen "bodoh", atau sekadar "komponen." Ada nama-nama lain untuk jenis komponen ini, dan, harus dicatat, makna yang terlampir dalam nama-nama ini, dari kasus ke kasus, berbeda dalam fitur-fitur tertentu. Secara umum, ide umum dari pendekatan ini adalah bahwa kita memiliki komponen kontainer yang bertanggung jawab untuk menyimpan keadaan dan berisi metode untuk mengelola keadaan, dan logika pembentukan antarmuka ditransfer ke komponen presentasi lainnya. Komponen ini hanya bertanggung jawab untuk menerima properti dari komponen kontainer dan untuk pembentukan antarmuka yang benar.
β
Ini adalah materi Dan Abramov di mana ia mengeksplorasi ide ini.
Kami mengubah kode aplikasi kami sesuai dengan pola Wadah / Komponen.
Pertama, mari kita perhatikan fakta bahwa sekarang semua yang ada di aplikasi dirakit dalam satu komponen
App
. Aplikasi ini dirancang untuk menyederhanakan strukturnya sebanyak mungkin, tetapi dalam proyek nyata, komponen
App
tidak masuk akal untuk mentransfer tugas rendering formulir dan memasukkan kode di dalamnya yang dirancang untuk mengatur kerja mekanisme internal formulir ini.
Tambahkan ke folder yang sama di mana file
App.js
berada, file
Form.js
, di mana kode komponen baru akan ditemukan. Kami mentransfer semua kode dari komponen
App
ke file ini, dan mengkonversi komponen
App
, yang sekarang diwakili oleh komponen berdasarkan kelas, menjadi komponen fungsional, tugas utama yang akan menjadi output dari komponen
Form
. Jangan lupa untuk mengimpor komponen
Form
ke dalam komponen
App
. Akibatnya, kode komponen
App
akan terlihat seperti ini:
import React, {Component} from "react" import Form from "./Form" function App() { return ( <Form /> ) } export default App
Inilah yang ditampilkan aplikasi di layar pada tahap kerja ini.
Aplikasi di browserDi kelas-kelas sebelumnya, saya memberi tahu Anda bahwa saya lebih suka komponen
App
menjadi sesuatu seperti "daftar isi" aplikasi, yang menunjukkan urutan urutan bagian-bagiannya yang ditampilkan pada halaman, diwakili oleh komponen lain yang didelegasikan tugas membuat fragmen aplikasi yang besar.
Kami telah sedikit memperbaiki struktur aplikasi, tetapi masalah utama, yang dinyatakan dalam kenyataan bahwa satu komponen memiliki terlalu banyak tanggung jawab, belum diselesaikan. Kami cukup mentransfer semua yang sebelumnya di komponen
App
ke komponen
Form
. Karena itu, sekarang kita akan menyelesaikan masalah ini. Untuk melakukan ini, buat, di folder yang sama di mana file
Form.js
dan
App.js
, file lain -
FormComponent.js
. File ini akan mewakili komponen presentasi yang bertanggung jawab untuk visualisasi formulir. Bahkan, Anda dapat menamainya secara berbeda, Anda dapat menyusun file komponen secara berbeda, semuanya tergantung pada kebutuhan dan skala proyek tertentu. File
Form.js
akan berisi logika formulir, yaitu kode komponen kontainer. Oleh karena itu, ubah nama menjadi
FormContainer.js
dan ubah perintah impor dalam kode komponen
App
, bawa ke formulir ini:
import Form from "./FormContainer"
Anda juga bisa mengganti nama komponen
Form
ke
FormContainer
, tetapi kami tidak akan melakukan ini. Sekarang kita akan mentransfer kode yang bertanggung jawab untuk merender formulir dari file
FormContainer.js
ke file
FormComponent.js
.
Komponen
FormComponent
akan berfungsi. Berikut adalah bagaimana kodenya akan terlihat pada tahap kerja ini:
function FormComponent(props) { return ( <main> <form> <input name="firstName" value={this.state.firstName} onChange={this.handleChange} placeholder="First Name" /> <br /> <input name="lastName" value={this.state.lastName} onChange={this.handleChange} placeholder="Last Name" /> <br /> <input name="age" value={this.state.age} onChange={this.handleChange} placeholder="Age" /> <br /> <label> <input type="radio" name="gender" value="male" checked={this.state.gender === "male"} onChange={this.handleChange} /> Male </label> <br /> <label> <input type="radio" name="gender" value="female" checked={this.state.gender === "female"} onChange={this.handleChange} /> Female </label> <br /> <select value={this.state.destination} name="destination" onChange={this.handleChange} > <option value="">-- Please Choose a destination --</option> <option value="germany">Germany</option> <option value="norway">Norway</option> <option value="north pole">North Pole</option> <option value="south pole">South Pole</option> </select> <br /> <label> <input type="checkbox" name="isVegan" onChange={this.handleChange} checked={this.state.isVegan} /> Vegan? </label> <br /> <label> <input type="checkbox" name="isKosher" onChange={this.handleChange} checked={this.state.isKosher} /> Kosher? </label> <br /> <label> <input type="checkbox" name="isLactoseFree" onChange={this.handleChange} checked={this.state.isLactoseFree} /> Lactose Free? </label> <br /> <button>Submit</button> </form> <hr /> <h2><font color="#3AC1EF">Entered information:</font></h2> <p>Your name: {this.state.firstName} {this.state.lastName}</p> <p>Your age: {this.state.age}</p> <p>Your gender: {this.state.gender}</p> <p>Your destination: {this.state.destination}</p> <p>Your dietary restrictions:</p> <p>Vegan: {this.state.isVegan ? "Yes" : "No"}</p> <p>Kosher: {this.state.isKosher ? "Yes" : "No"}</p> <p>Lactose Free: {this.state.isLactoseFree ? "Yes" : "No"}</p> </main> ) }
Jika Anda melihat kode ini, menjadi jelas bahwa kami tidak dapat membatasi diri hanya dengan mentransfernya dari file ke file, karena sekarang ada tautan ke negara (misalnya,
this.state.firstName
) dan event handler (
this.handleChange
), yang dulunya berada di komponen yang sama berdasarkan kelas tempat kode rendering ini berada. Sekarang, semua yang sebelumnya diambil dari kelas yang sama di mana kode rendering berada akan diambil dari properti yang diteruskan ke komponen. Ada beberapa masalah lain. Sekarang kita akan memperbaiki kode ini, tetapi pertama kita akan kembali ke kode komponen
Form
, yang sekarang ada di file
FormContainer.js
.
Metode
render()
-nya sekarang kosong. Kami membutuhkan komponen
FormComponent
untuk ditampilkan dalam metode ini dan kami perlu mengatur transfer properti yang diperlukan untuk itu. Kami mengimpor
FormComponent
ke file
Form
dan menampilkan
FormComponent
dalam metode
render()
, meneruskannya menjadi event handler dan, sebagai objek, status. Sekarang kode komponen
Form
akan terlihat seperti ini:
import React, {Component} from "react" import FormComponent from "./FormComponent" class Form extends Component { constructor() { super() this.state = { firstName: "", lastName: "", age: "", gender: "", destination: "", isVegan: false, isKosher: false, isLactoseFree: false } this.handleChange = this.handleChange.bind(this) } handleChange(event) { const {name, value, type, checked} = event.target type === "checkbox" ? this.setState({ [name]: checked }) : this.setState({ [name]: value }) } render() { return( <FormComponent handleChange={this.handleChange} data={this.state} /> ) } } export default Form
Kami akan
FormComponent
kode komponen
FormComponent
, membawanya ke formulir berikut:
import React from "react" function FormComponent(props) { return ( <main> <form> <input name="firstName" value={props.data.firstName} onChange={props.handleChange} placeholder="First Name" /> <br /> <input name="lastName" value={props.data.lastName} onChange={props.handleChange} placeholder="Last Name" /> <br /> <input name="age" value={props.data.age} onChange={props.handleChange} placeholder="Age" /> <br /> <label> <input type="radio" name="gender" value="male" checked={props.data.gender === "male"} onChange={props.handleChange} /> Male </label> <br /> <label> <input type="radio" name="gender" value="female" checked={props.data.gender === "female"} onChange={props.handleChange} /> Female </label> <br /> <select value={props.data.destination} name="destination" onChange={props.handleChange} > <option value="">-- Please Choose a destination --</option> <option value="germany">Germany</option> <option value="norway">Norway</option> <option value="north pole">North Pole</option> <option value="south pole">South Pole</option> </select> <br /> <label> <input type="checkbox" name="isVegan" onChange={props.handleChange} checked={props.data.isVegan} /> Vegan? </label> <br /> <label> <input type="checkbox" name="isKosher" onChange={props.handleChange} checked={props.data.isKosher} /> Kosher? </label> <br /> <label> <input type="checkbox" name="isLactoseFree" onChange={props.handleChange} checked={props.data.isLactoseFree} /> Lactose Free? </label> <br /> <button>Submit</button> </form> <hr /> <h2><font color="#3AC1EF">Entered information:</font></h2> <p>Your name: {props.data.firstName} {props.data.lastName}</p> <p>Your age: {props.data.age}</p> <p>Your gender: {props.data.gender}</p> <p>Your destination: {props.data.destination}</p> <p>Your dietary restrictions:</p> <p>Vegan: {props.data.isVegan ? "Yes" : "No"}</p> <p>Kosher: {props.data.isKosher ? "Yes" : "No"}</p> <p>Lactose Free: {props.data.isLactoseFree ? "Yes" : "No"}</p> </main> ) } export default FormComponent
Di sini kami memperbaiki kode dengan mempertimbangkan fakta bahwa komponen sekarang menerima data dan tautan ke event handler melalui properti.
Setelah semua transformasi ini, baik penampilan bentuk maupun cara kerjanya tidak akan berubah, tetapi kami telah memperbaiki struktur kode proyek, meskipun ukuran kode komponen
FormComponent
masih cukup besar. Namun, sekarang kode ini hanya memecahkan satu masalah, hanya bertanggung jawab untuk visualisasi formulir. Karena itu, bekerja dengannya sekarang jauh lebih mudah.
Sebagai hasilnya, kami telah mencapai pemisahan tanggung jawab antara komponen. Komponen
Form
dari file
FormContainer.js
sekarang secara eksklusif ditempati oleh logika aplikasi, sedangkan komponen
FormComponent
dari file
FormComponent.js
hanya berisi kode yang membentuk antarmuka aplikasi. Komponen
App
sekarang hanya bertanggung jawab untuk merakit halaman dari blok besar.
Perlu dicatat bahwa, mengingat keberadaan perpustakaan seperti
Redux
dan
Context
API yang baru dirilis, pola Container / Komponen yang dibahas di sini tidak lagi relevan seperti sebelumnya. Misalnya, Redux dapat mendukung keadaan global aplikasi yang dapat digunakan komponen.
Ringkasan
Dalam pelajaran ini, kami memeriksa penggunaan pola Wadah / Komponen, yang bertujuan membagi komponen menjadi komponen yang bertanggung jawab untuk pembentukan antarmuka aplikasi dan komponen yang bertanggung jawab untuk menyimpan status dan logika aplikasi. Menerapkan pola ini membantu meningkatkan struktur kode aplikasi Bereaksi dan memfasilitasi proses pengembangan. Lain kali kita akan mengerjakan proyek kursus.
Pembaca yang budiman! Pola desain apa yang Anda gunakan saat mengembangkan aplikasi Bereaksi?
