Bereaksi Tutorial Bagian 26: Arsitektur Aplikasi, Wadah / Pola Komponen

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

gambar

β†’ 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 komponen
Bagian 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 kursus

Pelajaran 44. Arsitektur Aplikasi, Wadah / Pola Komponen


β†’ Asli

Terkadang 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 browser

Di 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?

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


All Articles