Hari ini kami menerbitkan bagian kedua dari terjemahan materi, yang dikhususkan untuk pengembangan aplikasi React skala besar. Di sini kita akan berbicara tentang mengelola keadaan aplikasi, perutean, dan pengembangan antarmuka.

Bagian 1:
Pedoman praktis untuk mengembangkan aplikasi Bereaksi skala besar. Perencanaan, Tindakan, Sumber Data, dan APIBagian 2:
Pedoman praktis untuk mengembangkan aplikasi Bereaksi skala besar. Bagian 2: manajemen negara, peruteanManajemen status aplikasi, integrasi Redux, routing organisasi
Di sini kita akan berbicara tentang bagaimana Anda dapat memperluas fungsionalitas Redux agar dapat melakukan operasi kompleks dalam aplikasi secara teratur. Jika mekanisme seperti itu diimplementasikan dengan buruk, mereka dapat melanggar pola yang digunakan dalam merancang repositori.
Fungsi generator JavaScript dapat memecahkan banyak masalah yang terkait dengan pemrograman asinkron. Faktanya adalah bahwa fungsi-fungsi ini dapat dimulai dan dihentikan atas permintaan programmer. Redux-saga middleware menggunakan konsep ini untuk mengelola aspek aplikasi yang bermasalah. Secara khusus, kita berbicara tentang memecahkan masalah seperti itu, yang tidak dapat diselesaikan dengan bantuan reduksi, disajikan dalam bentuk fungsi murni.
▍Menyelesaikan tugas yang tidak dapat diselesaikan dengan fungsi murni
Pertimbangkan skenario berikut. Anda ditawari mengerjakan aplikasi yang dirancang untuk perusahaan yang bekerja di pasar real estat. Klien ingin mendapatkan situs web baru yang lebih baik. Yang Anda inginkan ada API REST, Anda memiliki tata letak semua halaman yang disiapkan menggunakan Zapier, Anda telah menguraikan rencana aplikasi. Tapi kemudian masalah besar muncul.
Perusahaan klien telah lama menggunakan sistem manajemen konten (CMS) tertentu. Karyawan perusahaan sangat menyadari sistem ini, sehingga pelanggan tidak ingin beralih ke CMS baru hanya untuk membuatnya lebih mudah untuk menulis posting baru di blog perusahaan. Selain itu, Anda juga perlu menyalin publikasi yang ada dari blog ke situs baru, dan ini juga dapat menyebabkan masalah.
Yang menyenangkan adalah bahwa CMS yang digunakan oleh klien memiliki API yang nyaman di mana Anda dapat mengakses publikasi dari blog. Tetapi, jika Anda membuat agen untuk bekerja dengan API ini, situasinya diperumit oleh fakta bahwa
ia terletak di server tertentu, di mana data disajikan sama sekali tidak seperti yang Anda butuhkan.
Ini adalah contoh masalah, sesuatu yang dapat mencemari kode aplikasi, karena di sini Anda harus memasukkan dalam mekanisme proyek untuk bekerja dengan API baru yang digunakan untuk mengunduh posting blog. Anda dapat menangani situasi ini dengan redux-saga.
Lihatlah diagram berikut. Inilah cara aplikasi dan API kami berinteraksi. Kami mengunduh publikasi di latar belakang menggunakan redux-saga.
Diagram Aplikasi Menggunakan Redux dan Penyimpanan redux-sagaDi sini, komponen mengirimkan tindakan
GET.BLOGS
. Aplikasi ini menggunakan redux-saga, jadi permintaan ini akan dicegat. Setelah itu, fungsi generator akan mengunduh data dari penyimpanan data di latar belakang dan memperbarui status aplikasi yang didukung oleh Redux.
Berikut adalah contoh bagaimana fungsi generator untuk memuat publikasi (fungsi tersebut disebut “sagas”) mungkin terlihat dalam situasi yang dijelaskan. Sagas dapat digunakan dalam skenario lain. Misalnya, untuk mengatur penyimpanan data pengguna (katakanlah, itu bisa menjadi token), karena ini adalah contoh lain dari tugas yang fungsi murninya tidak cocok.
... function* fetchPosts(action) { if (action.type === WP_POSTS.LIST.REQUESTED) { try { const response = yield call(wpGet, { model: WP_POSTS.MODEL, contentType: APPLICATION_JSON, query: action.payload.query, }); if (response.error) { yield put({ type: WP_POSTS.LIST.FAILED, payload: response.error.response.data.msg, }); return; yield put({ type: WP_POSTS.LIST.SUCCESS, payload: { posts: response.data, total: response.headers['x-wp-total'], query: action.payload.query, }, view: action.view, }); } catch (e) { yield put({ type: WP_POSTS.LIST.FAILED, payload: e.message }); ...
Kisah yang disajikan di sini mengharapkan tindakan seperti
WP_POSTS.LIST.REQUESTED
. Dengan menerima tindakan seperti itu, ia memuat data dari API. Dia, setelah menerima data, mengirimkan tindakan lain -
WP_POSTS.LIST.SUCCESS
. Pemrosesannya mengarah ke memperbarui repositori menggunakan peredam yang sesuai.
▍ Pengenalan reduksi
Saat mengembangkan aplikasi besar, tidak mungkin merencanakan terlebih dahulu perangkat dari semua model yang diperlukan. Selain itu, seiring dengan meningkatnya ukuran aplikasi, penggunaan teknologi memperkenalkan reduksi membantu menghemat sejumlah besar jam kerja. Teknik ini memungkinkan pengembang untuk menambahkan reducers baru ke sistem tanpa menulis ulang seluruh repositori.
Ada
perpustakaan yang dirancang untuk membuat repositori Redux yang dinamis. Namun, saya lebih suka mekanisme memperkenalkan reduksi, karena memberikan pengembang tingkat fleksibilitas tertentu. Misalnya, aplikasi yang sudah ada dapat dilengkapi dengan mekanisme ini tanpa perlu serius mengatur ulang aplikasi tersebut.
Pengenalan reduksi adalah bentuk pemisahan kode. Komunitas pengembang Bereaksi dengan antusias merangkul teknologi ini. Saya akan menggunakan potongan kode ini untuk menunjukkan tampilan dan fitur mekanisme implementasi reduksi.
Pertama, mari kita lihat integrasinya dengan Redux:
... const withConnect = connect( mapStateToProps, mapDispatchToProps, ); const withReducer = injectReducer({ key: BLOG_VIEW, reducer: blogReducer, }); class BlogPage extends React.Component { ... } export default compose( withReducer, withConnect, )(BlogPage);
Kode ini adalah bagian dari file
BlogPage.js
yang berisi komponen aplikasi.
Di sini kita, dalam perintah ekspor, tidak menggunakan fungsi
connect
, tetapi fungsi
compose
. Ini adalah salah satu fungsi dari pustaka Redux yang memungkinkan Anda membuat beberapa fungsi. Daftar fungsi yang dilewati untuk
compose
harus dibaca dari kanan ke kiri atau dari bawah ke atas.
Anda dapat belajar dari
dokumentasi Redux bahwa fungsi
compose
memungkinkan Anda untuk membuat transformasi fungsi yang sangat bersarang. Dalam hal ini, programmer dibebaskan dari kebutuhan untuk menggunakan struktur yang sangat panjang. Konstruksi ini terlihat seperti baris kode yang mewakili panggilan ke beberapa fungsi dengan memberikannya hasil panggilan ke fungsi lain sebagai argumen. Dokumentasi mencatat bahwa fungsi
compose
harus digunakan dengan hati-hati.
Fungsi paling kanan dalam suatu komposisi dapat mengambil banyak argumen, tetapi hanya satu argumen yang dapat diteruskan ke fungsi yang mengikutinya. Sebagai hasilnya, dengan memanggil fungsi yang dihasilkan dari menggunakan
compose
, kita meneruskannya apa yang diperlukan dari fungsi aslinya, yang berada di sebelah kanan semua yang lain. Itulah sebabnya kami meneruskan fungsi tulis ke fungsi
withConnect
sebagai parameter terakhir. Hasilnya, fungsi
compose
dapat digunakan seperti fungsi
connect
.
▍ Routing dan Redux
Ada sejumlah alat yang digunakan untuk memecahkan masalah perutean dalam aplikasi. Pada bagian ini, bagaimanapun, kita akan fokus pada perpustakaan
react-router-dom . Kami akan memperluas kemampuannya sehingga dapat bekerja dengan Redux.
Paling sering, router Bereaksi digunakan seperti ini: komponen root terlampir dalam tag
BrowserRouter
, dan wadah anak dibungkus dengan metode
withRouter()
dan diekspor (
berikut adalah contoh).
Dengan pendekatan ini, komponen anak menerima, melalui mekanisme
props
, objek
history
berisi beberapa properti khusus untuk sesi pengguna saat ini. Ada beberapa metode dalam objek ini yang dapat digunakan untuk mengontrol navigasi.
Opsi perutean ini dapat menyebabkan masalah pada aplikasi besar. Ini disebabkan oleh fakta bahwa mereka tidak memiliki objek
history
tersentralisasi. Selain itu, komponen yang tidak dirender dengan
<Route>
tidak dapat berfungsi dengan objek
history
. Berikut ini contoh menggunakan
<Route>
:
<Route path="/" exact component={HomePage} />
Untuk mengatasi masalah ini, kita akan menggunakan pustaka yang
terhubung-bereaksi-router , yang akan memungkinkan kita untuk membuat rute menggunakan metode
dispatch
. Integrasi perpustakaan ini ke dalam proyek akan memerlukan beberapa modifikasi. Secara khusus, akan diperlukan untuk membuat peredam baru yang dirancang khusus untuk rute (ini cukup jelas), dan juga untuk menambahkan beberapa mekanisme tambahan ke sistem.
Setelah konfigurasi selesai, sistem perutean baru dapat digunakan melalui Redux. Jadi, navigasi dalam aplikasi dapat diimplementasikan dengan mengirimkan tindakan.
Untuk mengambil keuntungan dari kapabilitas pustaka yang terhubung-bereaksi-router dalam komponen, kami cukup memetakan metode
dispatch
ke repositori, melakukan ini sesuai dengan kebutuhan aplikasi. Berikut adalah contoh kode yang menunjukkan penggunaan pustaka router reaksi-terkoneksi (agar kode ini dapat berfungsi, Anda perlu seluruh sistem untuk dikonfigurasikan untuk menggunakan router reaksi-terkoneksi).
import { push } from 'connected-react-router' ... const mapDispatchToProps = dispatch => ({ goTo: payload => { dispatch(push(payload.path)); }, }); class DemoComponent extends React.Component { render() { return ( <Child onClick={ () => { this.props.goTo({ path: `/gallery/`}); /> } ...
Di sini metode
goTo
mengirim tindakan yang mendorong URL yang diperlukan
goTo
tumpukan riwayat browser. Sebelumnya, metode
goTo
telah
goTo
ke repositori. Oleh karena itu, metode ini diteruskan ke
DemoComponent
di objek
props
.
Antarmuka pengguna yang dinamis dan kebutuhan aplikasi yang berkembang
Seiring waktu, terlepas dari adanya backend yang memadai untuk aplikasi dan bagian klien yang berkualitas tinggi, beberapa elemen antarmuka pengguna mulai mempengaruhi kerja pengguna dengan buruk. Hal ini disebabkan oleh implementasi komponen yang tidak rasional, yang, pada pandangan pertama, tampak sangat sederhana. Di bagian ini, kami akan membahas rekomendasi untuk membuat beberapa widget. Implementasinya yang benar, seiring pertumbuhan aplikasi, menjadi lebih rumit.
Loading Pemuatan Malas dan React. Suspense
Bagian terbaik tentang sifat asinkron dari JavaScript adalah memanfaatkan potensi penuh peramban. Mungkin kebaikan sebenarnya adalah bahwa untuk memulai proses tertentu Anda tidak perlu menunggu penyelesaian tugas sebelumnya. Namun, pengembang tidak dapat mempengaruhi jaringan dan kecepatan berbagai bahan yang diperlukan untuk berfungsinya situs.
Subsistem jaringan biasanya dianggap tidak dapat diandalkan dan rentan kesalahan.
Pengembang, dalam upaya membuat aplikasinya setinggi mungkin, dapat dikenakan banyak pemeriksaan dan mencapai keberhasilannya. Tetapi masih ada beberapa hal, seperti status koneksi jaringan atau waktu respons server, yang tidak dapat dipengaruhi pengembang.
Tetapi pencipta perangkat lunak tidak berusaha membenarkan kerja aplikasi yang berkualitas rendah dengan frasa seperti "ini bukan urusan saya." Mereka menemukan cara menarik untuk menangani masalah jaringan.
Di beberapa bagian aplikasi
front-end, Anda mungkin perlu menunjukkan beberapa bahan cadangan (seperti memuat lebih cepat dari bahan asli). Ini akan menyelamatkan pengguna dari merenungkan "berkedut" dari halaman memuat atau, lebih buruk lagi, tentang ikon tersebut.
Pengguna lebih baik tidak melihat hal seperti ini.Teknologi React Suspense memungkinkan Anda untuk mengatasi masalah seperti itu. Misalnya, ini memungkinkan Anda untuk menampilkan indikator tertentu selama pemuatan data. Meskipun ini juga bisa dilakukan secara manual dengan mengatur properti
isLoaded
menjadi
true
, menggunakan Suspense API membuat kode lebih bersih.
Di sini Anda dapat menonton video yang bagus tentang Suspense, di mana Jared Palmer memperkenalkan pemirsa ke teknologi ini dan menunjukkan beberapa fitur-fiturnya menggunakan contoh
aplikasi nyata .
Begini cara aplikasi bekerja tanpa menggunakan Suspense.
Aplikasi tempat Suspense tidak digunakanMelengkapi komponen dengan dukungan Suspense jauh lebih mudah daripada menggunakan seluruh aplikasi
isLoaded
. Mari kita mulai dengan meletakkan wadah
App
induk di
React.StrictMode
. Kami memastikan bahwa di antara modul Bereaksi yang digunakan dalam aplikasi, tidak akan ada yang dianggap usang.
<React.Suspense fallback={<Spinner size="large" />}> <ArtistDetails id={this.props.id}/> <ArtistTopTracks /> <ArtistAlbums id={this.props.id}/> </React.Suspense>
Komponen yang dibungkus dengan tag
React.Suspense
, selama pemuatan konten utama, muat dan tampilkan apa yang ditentukan dalam properti
fallback
. Kita harus berusaha untuk memastikan bahwa komponen yang digunakan dalam properti
fallback
memiliki volume sekecil mungkin dan disusun sesederhana mungkin.
Aplikasi yang menggunakan Suspense▍ Komponen adaptif
Dalam aplikasi front-end yang besar, manifestasi dari pola berulang adalah umum. Pada saat yang sama, di awal pekerjaan, ini bisa hampir sama sekali tidak terlihat. Tidak ada yang bisa dilakukan tentang itu, tetapi Anda harus menemukan ini.
Misalnya, ada dua model dalam aplikasi. Salah satunya dimaksudkan untuk deskripsi trek balap, dan yang kedua - untuk deskripsi mobil. Halaman daftar mobil menggunakan elemen persegi. Masing-masing berisi gambar dan deskripsi singkat.
Daftar jejak menggunakan elemen serupa. Fitur utama mereka adalah bahwa, selain gambar dan deskripsi trek, mereka juga memiliki bidang kecil yang menunjukkan apakah mungkin bagi para penonton lomba yang berlangsung di trek ini untuk membeli sesuatu untuk dimakan.
Elemen untuk deskripsi mobil dan elemen untuk deskripsi trekKedua komponen ini sedikit berbeda satu sama lain dalam hal gaya (mereka memiliki warna latar belakang yang berbeda). Komponen yang menggambarkan rute berisi beberapa informasi tambahan tentang objek dunia nyata yang dijelaskannya, sedangkan komponen yang melambangkan mobil tidak memiliki informasi tersebut. Contoh ini hanya menunjukkan dua model. Dalam aplikasi besar, banyak model serupa dapat diketik, hanya berbeda dalam hal-hal kecil.
Penciptaan komponen independen yang terpisah untuk masing-masing entitas ini bertentangan dengan akal sehat.
Seorang programmer dapat menyelamatkan dirinya dari kebutuhan untuk menulis fragmen kode yang hampir sepenuhnya saling mengulang. Ini dapat dilakukan melalui pengembangan komponen adaptif. Mereka, dalam pekerjaan, memperhitungkan lingkungan di mana mereka dimuat. Pertimbangkan bilah pencarian aplikasi tertentu.
Bilah pencarianIni akan digunakan pada banyak halaman. Pada saat yang sama, perubahan kecil akan dilakukan pada penampilan dan urutan kerjanya pada halaman yang berbeda. Misalnya, pada halaman muka proyek, itu akan menjadi sedikit lebih besar dari pada halaman lain. Untuk mengatasi masalah ini, Anda dapat membuat satu komponen tunggal yang akan ditampilkan sesuai dengan properti yang ditransfer ke sana.
static propTypes = { open: PropTypes.bool.isRequired, setOpen: PropTypes.func.isRequired, goTo: PropTypes.func.isRequired, };
Dengan menggunakan teknik ini, Anda dapat mengontrol penggunaan kelas HTML saat merender elemen tersebut, yang memungkinkan Anda untuk memengaruhi penampilan mereka.
Situasi menarik lainnya di mana komponen adaptif dapat menemukan aplikasi adalah mekanisme untuk memecah material tertentu menjadi beberapa halaman. Bilah navigasi dapat ada di setiap halaman aplikasi. Contoh panel ini di setiap halaman akan hampir persis sama dengan di halaman lain.
Panel paginationMisalkan aplikasi tertentu membutuhkan panel yang serupa. Saat mengerjakan aplikasi ini, pengembang mematuhi persyaratan yang diartikulasikan tepat waktu. Dalam situasi seperti itu, komponen adaptif yang digunakan untuk memecah materi menjadi halaman hanya perlu melewati beberapa properti. Ini adalah
URL
dan jumlah elemen per halaman.
Ringkasan
Ekosistem Bereaksi telah menjadi sangat dewasa hari ini sehingga tidak mungkin ada orang yang perlu “menciptakan sepeda” pada setiap tahap pengembangan aplikasi. Meskipun ini berperan di tangan pengembang, itu mengarah pada fakta bahwa menjadi sulit untuk memilih apa yang bekerja dengan baik untuk setiap proyek tertentu.
Setiap proyek memiliki keunikan dalam hal cakupan dan fungsinya. Tidak ada pendekatan tunggal atau aturan universal dalam mengembangkan aplikasi Bereaksi. Karena itu, sebelum memulai pengembangan, penting untuk merencanakannya dengan benar.
Saat merencanakan, sangat mudah untuk memahami alat mana yang secara langsung dibuat untuk proyek dan mana yang jelas tidak cocok untuknya, karena terlalu besar untuknya. Misalnya, aplikasi yang terdiri dari 2-3 halaman dan melakukan sangat sedikit permintaan ke API tertentu tidak memerlukan penyimpanan data yang serupa dengan yang kita bicarakan. Saya siap melangkah lebih jauh dalam pertimbangan ini, dan mengatakan bahwa dalam proyek kecil Anda tidak perlu menggunakan Redux.
Pada tahap perencanaan aplikasi, saat menggambar tata letak halaman-halamannya, mudah untuk melihat bahwa banyak komponen serupa digunakan pada halaman-halaman ini. Jika Anda mencoba menggunakan kembali kode komponen tersebut atau berupaya menulis komponen universal, ini akan membantu menghemat banyak waktu dan upaya.
Dan akhirnya, saya ingin mencatat bahwa data adalah inti dari aplikasi apa pun. Dan Bereaksi aplikasi tidak terkecuali. Ketika skala aplikasi bertambah, volume data yang diproses bertambah, muncul mekanisme perangkat lunak tambahan untuk bekerja dengannya. Sesuatu seperti ini, jika aplikasi itu dirancang dengan buruk, dapat dengan mudah "menghancurkan" programmer, mengisinya dengan tugas-tugas yang rumit dan membingungkan. Jika, dalam proses perencanaan, masalah penggunaan gudang data diputuskan di muka, jika urutan tindakan, reduksi, sag dipikirkan sebelumnya, maka mengerjakan aplikasi akan jauh lebih mudah.
Pembaca yang budiman! Jika Anda tahu ada perpustakaan atau metodologi pengembangan yang berkinerja baik saat membuat aplikasi Bereaksi skala besar, silakan bagikan.
