Pengantar React kami hilang

React adalah pustaka JavaScript paling populer di dunia. Tetapi perpustakaan ini tidak bagus karena populer, tetapi karena populer karena bagus. Sebagian besar tutorial pengantar React yang ada dimulai dengan contoh cara menggunakan library. Namun panduan ini tidak menjelaskan apa pun tentang mengapa React adalah pilihan yang tepat.



Pendekatan ini ada kelebihannya. Jika seseorang berusaha untuk segera berlatih sambil menguasai React, dia hanya perlu melihat ke dalam dokumentasi resmi dan mulai berbisnis . Materi ini (di sini , jika Anda tertarik, versi videonya) ditulis untuk mereka yang ingin menemukan jawaban atas pertanyaan-pertanyaan berikut: β€œWhy React? Mengapa React bekerja seperti ini? Mengapa React API dirancang seperti itu? "











Mengapa React?



Hidup menjadi lebih mudah jika komponen tidak mengetahui komunikasi jaringan, logika bisnis aplikasi, atau statusnya. Komponen seperti itu, menerima parameter masukan yang sama, selalu membentuk elemen visual yang sama.



Ketika perpustakaan React hadir, itu secara fundamental mengubah cara kerja kerangka kerja JavaScript dan perpustakaan. Sementara proyek serupa lainnya mempromosikan ide MVC, MVVM dan sejenisnya, dalam React pendekatan yang berbeda diambil. Yakni, rendering komponen visual aplikasi diisolasi dari penyajian model. Berkat React, arsitektur yang benar-benar baru telah muncul di ekosistem frontend JavaScript - Flux.



Mengapa tim React melakukan ini? Mengapa pendekatan ini lebih baik daripada pendekatan sebelumnya, seperti arsitektur MVC dan kode spaghetti yang ditulis dalam jQuery? Jika Anda adalah tipe yang tertarik dengan pertanyaan-pertanyaan ini, Anda dapat menonton ceramah 2013 ini di Pengembangan Aplikasi JavaScript di Facebook.



Pada 2013, Facebook baru saja menyelesaikan beberapa pekerjaan integrasi yang serius ke dalam platform obrolannya. Fitur baru ini dibangun di hampir setiap halaman proyek, obrolan memengaruhi skenario biasa bekerja dengan platform. Itu adalah aplikasi kompleks yang tertanam di aplikasi lain yang sebelumnya tidak mudah. Tim Facebook harus berurusan dengan tugas-tugas nontrivial, berurusan dengan mutasi DOM yang tidak terkendali dan kebutuhan untuk memberikan pengalaman pengguna asynchronous paralel di lingkungan baru.



Misalnya, bagaimana Anda mengetahui sebelumnya apa yang akan ditampilkan di layar dalam situasi di mana apa pun, kapan pun dan dengan alasan apa pun, dapat mengakses DOM dan membuat perubahan di sana? Bagaimana cara memastikan bahwa apa yang dilihat pengguna diplot dengan benar?



Menggunakan alat front-end populer yang ada sebelum React, hal seperti itu tidak dapat dijamin. Dalam aplikasi web awal, "kondisi balapan" di DOM adalah salah satu masalah paling umum.



Kurangnya determinisme = komputasi paralel + keadaan yang bisa berubah.



Martin Oderski




Tugas utama tim pengembang React adalah memecahkan masalah ini. Mereka mengatasinya dengan dua pendekatan inovatif utama:



  • Pengikatan data searah menggunakan arsitektur Flux.
  • Keabadian status komponen. Setelah status komponen disetel, status tersebut tidak dapat lagi diubah. Perubahan status tidak mempengaruhi komponen yang dirender. Sebaliknya, perubahan tersebut mengarah pada keluaran tampilan baru dengan status baru.


Cara termudah yang kami temukan untuk menyusun dan merender komponen, dari sudut pandang konseptual, adalah dengan mengarahkan nol mutasi sama sekali.



Tom Ochchino, JSConfUS 2013




Pustaka React mampu secara dramatis mengurangi masalah mutasi yang tidak terkontrol dengan menggunakan arsitektur Flux. Alih-alih melampirkan event handler untuk memicu pembaruan DOM ke sejumlah sembarang objek (model), perpustakaan React memberi pengembang satu cara untuk mengelola status komponen. Ini adalah pengiriman tindakan yang memengaruhi gudang data. Ketika status penyimpanan berubah, sistem meminta komponen untuk dirender.





Arsitektur Flux



Ketika saya ditanya mengapa saya harus memperhatikan React, saya memberikan jawaban sederhana: "Intinya adalah, kita membutuhkan rendering tampilan deterministik, dan React membuat tugas ini jauh lebih mudah."



Perhatikan bahwa membaca data dari DOM untuk mengimplementasikan beberapa logika adalah anti-pola. Siapapun yang melakukan ini bertentangan dengan tujuan penggunaan React. Sebaliknya, data harus dibaca dari penyimpanan, dan keputusan berdasarkan data tersebut harus dibuat sebelum komponen terkait dibuat.



Jika rendering deterministik komponen adalah satu-satunya hal tentang React, maka itu saja akan menjadi inovasi yang hebat. Tetapi tim pengembangan React tidak berhenti di situ. Tim ini menyajikan dunia dengan perpustakaan yang memiliki fitur unik dan menarik lainnya. Dan seiring perkembangan proyek, React menambahkan hal-hal yang lebih berguna.



JSX



JSX adalah ekstensi JavaScript yang memungkinkan Anda membuat komponen antarmuka pengguna secara deklaratif. JSX memiliki beberapa fitur penting berikut:





Jika, sebelum munculnya JSX, antarmuka harus dideskripsikan secara deklaratif, maka tidak mungkin dilakukan tanpa menggunakan template HTML. Pada masa itu, tidak ada standar yang diterima secara umum untuk membuat templat semacam itu. Setiap kerangka menggunakan sintaksnya sendiri. Sintaks ini harus dipelajari oleh seseorang yang, misalnya, perlu mengulang melalui beberapa data, menyematkan nilai dari variabel ke dalam template teks, atau memutuskan komponen antarmuka mana yang akan ditampilkan dan mana yang tidak.



Saat ini, jika Anda melihat alat frontend yang berbeda, Anda akan menemukan bahwa Anda *ngFortidak dapat melakukannya tanpa sintaks khusus, seperti arahan dari Angular. Tapi, karena JSX bisa disebut superset dari JavaScript, membuat markup JSX bisa memanfaatkan kemampuan JS yang ada.



Misalnya, Anda dapat melakukan iterasi atas sekumpulan elemen menggunakan metode Array.prototype.map. Anda dapat menggunakan operator logika, mengatur rendering bersyarat menggunakan operator terner. Anda dapat menggunakan fungsi murni , Anda dapat membuat string menggunakan literal template . Secara umum, semua fitur JavaScript tersedia bagi mereka yang mendeskripsikan antarmuka di JSX. Saya pikir ini adalah keuntungan besar dari React dibandingkan framework dan library lainnya.



Berikut contoh kode JSX:



const ItemList = ({ items }) => (
  <ul>
    {items.map((item) => (
      <li key={item.id}>
        <div>{item.name}</div>
      </li>
    ))}
  </ul>
);


Benar, saat bekerja dengan JSX, Anda perlu mempertimbangkan beberapa fitur yang, pada awalnya, mungkin tampak tidak biasa.



  • , , HTML. , class className. camelCase.
  • , , , JSX- key. . id, key.


React tidak memaksakan pada pengembang satu-satunya cara yang benar untuk bekerja dengan CSS. Misalnya, Anda bisa meneruskan objek JavaScript dengan gaya ke komponen dengan menuliskannya ke properti style. Dengan pendekatan ini, sebagian besar nama gaya yang sudah dikenal akan diganti dengan yang setara dengan CamelCase. Tetapi kemungkinan untuk bekerja dengan gaya tidak terbatas pada ini. Dalam praktiknya, saya secara bersamaan menggunakan pendekatan berbeda untuk menata aplikasi React. Pendekatan mana yang Anda pilih tergantung pada gaya yang Anda inginkan. Misalnya, saya menggunakan gaya global untuk mengatur gaya tema aplikasi dan tata letak halaman, dan gaya lokal untuk menyesuaikan tampilan komponen tertentu.



Berikut adalah fitur gaya React favorit saya:



  • CSS-, . , . β€” , .
  • CSS- β€” CSS- . JavaScript-. CSS-, . Next.js, , .
  • Paket styled-jsx , yang memungkinkan Anda untuk mendeklarasikan gaya langsung di kode komponen React Anda. Ini mirip dengan menggunakan tag <style>di HTML. Ruang lingkup gaya seperti itu bisa disebut "hyperlocal". Intinya adalah bahwa gaya hanya mempengaruhi elemen yang diterapkan dan anaknya. Saat menggunakan Next.js, paket bergaya-jsx dapat digunakan tanpa perlu menghubungkan dan mengkonfigurasi sesuatu sendiri.


Peristiwa sintetis



React memberi kita pembungkus lintas-browser SyntheticEventsyang mewakili peristiwa sintetis dan dirancang untuk menyatukan pekerjaan dengan peristiwa DOM. Peristiwa sintetis berguna karena beberapa alasan:



  1. , . .
  2. . , , , JavaScript HTML, . . , , React- .
  3. . . , , . , , , . . , . , JavaScript, .


Perhatikan bahwa karena penggunaan kumpulan acara, properti acara sintetis tidak dapat diakses dari fungsi asinkron. Untuk mengimplementasikan skema kerja seperti itu, Anda perlu mengambil data dari objek acara dan menuliskannya ke variabel yang dapat diakses oleh fungsi asynchronous.



Siklus hidup komponen



Konsep siklus hidup komponen React berfokus pada perlindungan status komponen. Status komponen tidak boleh berubah saat sedang ditampilkan. Ini dicapai karena skema kerja berikut: komponen berada dalam status tertentu dan diberikan. Kemudian, berkat peristiwa siklus hidup, menjadi mungkin untuk menerapkan efek padanya, Anda dapat memengaruhi keadaannya, bekerja dengan peristiwa.



Memahami siklus hidup komponen React sangat penting untuk mengembangkan antarmuka dan pada saat yang sama tidak bertarung dengan React, tetapi gunakan pustaka ini seperti yang dimaksudkan oleh para pengembangnya. "Perkelahian" dengan React, seperti salah mengubah status komponen atau membaca data dari DOM, meniadakan kekuatan library ini.



Di React, dimulai dengan versi 0.14, terdapat sintaks deskripsi komponen berbasis kelas yang memungkinkan Anda menangani peristiwa siklus hidup komponen. Ada tiga tahapan penting dalam siklus hidup komponen React: Pasang, Perbarui, dan Lepas.





Siklus hidup komponen



Tahap Pembaruan dapat dibagi menjadi tiga bagian: Render (rendering), Precommit (bersiap untuk membuat perubahan pada pohon DOM), Komit (membuat perubahan pada pohon DOM).





Struktur tahap Pembaruan



Mari kita bahas tahap-tahap siklus hidup komponen ini secara lebih rinci:



  • Render β€” . render() , . , JSX.
  • Precommit β€” DOM, getSnapShotBeforeUpdate. , , .
  • Komit - Selama fase siklus hidup komponen ini, React memperbarui DOM dan referensi . Di sini Anda bisa menggunakan metode componentDidUpdateatau kail useEffect. Di sinilah Anda dapat melakukan efek, menjadwalkan pembaruan, menggunakan DOM, dan tugas serupa lainnya.


Dan Abramov telah menyiapkan diagram yang sangat bagus yang menggambarkan cara kerja mekanisme siklus hidup komponen.





Siklus Hidup Komponen React Menurut



pendapat saya, merepresentasikan komponen sebagai kelas berumur panjang bukanlah model mental React terbaik. Ingatlah bahwa status komponen React tidak boleh bermutasi. Keadaan usang harus diganti dengan yang baru. Setiap penggantian tersebut menyebabkan komponen dirender ulang. Ini memberi React apa yang bisa dibilang fitur paling penting dan paling berharga: dukungan untuk pendekatan deterministik untuk merender visual komponen.



Perilaku ini paling baik dianggap sebagai berikut: setiap kali komponen dirender, pustaka memanggil fungsi deterministik yang mengembalikan JSX. Fungsi ini seharusnya tidak menimbulkan efek sampingnya sendiri. Tetapi dia, jika dia membutuhkannya, dapat meneruskan permintaan ke React untuk melakukan efek seperti itu.



Dengan kata lain, masuk akal untuk memikirkan sebagian besar komponen React sebagai fungsi murni yang mengambil parameter input dan mengembalikan JSX. Fungsi murni memiliki beberapa fitur berikut:



  • Ketika diberi masukan yang sama, mereka selalu mengembalikan keluaran yang sama (mereka deterministik).
  • Mereka tidak memiliki efek samping (yaitu, mereka tidak bekerja dengan sumber daya jaringan, tidak mengeluarkan apa pun ke konsol, tidak menulis apa pun, localStoragedan sebagainya).


Perhatikan bahwa jika efek samping diperlukan agar komponen dapat bekerja, Anda dapat mengeksekusinya dengan menggunakan useEffectatau merujuk ke pembuat tindakan yang diteruskan ke komponen melalui parameter input dan memungkinkan efek samping ditangani di luar komponen .



React Hooks



React 16.8 memperkenalkan konsep baru yang disebut React hooks. Ini adalah fungsi yang memungkinkan Anda untuk terhubung ke kejadian siklus hidup komponen tanpa menggunakan sintaks kelas dan tanpa bergantung pada metode siklus hidup komponen. Akibatnya, menjadi mungkin untuk membuat komponen bukan dalam bentuk kelas, tetapi dalam bentuk fungsi.



Memanggil hook, secara umum, berarti efek samping - yang memungkinkan komponen bekerja dengan statusnya dan dengan subsistem I / O. Efek samping adalah setiap perubahan status yang terlihat di luar fungsi, kecuali untuk perubahan nilai yang dikembalikan oleh fungsi tersebut.



Hook useEffectmemungkinkan Anda mengantrekan efek samping untuk dieksekusi nanti. Mereka akan dipanggil pada waktu yang tepat dalam siklus hidup komponen. Waktu ini bisa datang segera setelah komponen dipasang (misalnya, ketika metode siklus hidup componentDidMount dipanggil ), selama fase Komit (metode componentDidUpdate ), tepat sebelum komponen dilepas ( componentWillUnmount ).



Perhatikan bahwa ada tiga metode siklus hidup komponen yang terkait dengan satu hook? Intinya di sini adalah bahwa hook memungkinkan Anda untuk menggabungkan logika terkait, dan tidak "menatanya", seperti sebelumnya, sesuai dengan metode yang berbeda dari siklus hidup komponen.



Banyak komponen perlu melakukan beberapa tindakan saat dipasang, sesuatu perlu diperbarui setiap kali komponen digambar ulang, dan sumber daya harus segera dibebaskan sebelum melepas komponen untuk mencegah kebocoran memori. Berkat penggunaannya, useEffectsemua tugas ini dapat diselesaikan dalam satu fungsi, tanpa membagi solusinya menjadi 3 metode berbeda, tanpa mencampur kode mereka dengan kode tugas lain yang tidak terkait dengannya, tetapi juga memerlukan metode ini.



Inilah yang diberikan React hooks:



  • Mereka memungkinkan Anda untuk membuat komponen yang direpresentasikan sebagai fungsi daripada sebagai kelas.
  • Mereka membantu Anda mengatur kode Anda dengan lebih baik.
  • Mereka membuatnya lebih mudah untuk berbagi logika yang sama di berbagai komponen.
  • Pengait baru dapat dibuat dengan membuat pengait yang sudah ada (memanggilnya dari pengait lain).


Secara umum, kami merekomendasikan penggunaan komponen fungsional dan pengait daripada komponen berbasis kelas. Komponen fungsional biasanya lebih kompak daripada komponen berbasis kelas. Kode mereka lebih terorganisir, lebih mudah dibaca, lebih dapat digunakan kembali, dan lebih mudah untuk diuji.



Komponen Penampung dan Komponen Presentasi



Dalam upaya untuk meningkatkan modularitas komponen dan kegunaannya kembali, saya fokus pada pengembangan dua jenis komponen:



  • Komponen penampung adalah komponen yang terhubung ke sumber data dan dapat memiliki efek samping.
  • Biji presentasi, sebagian besar, adalah biji murni yang, dengan props dan konteks yang sama, selalu mengembalikan JSX yang sama.


Komponen murni tidak sama dengan kelas dasar React.PureComponent , yang dinamai demikian karena tidak aman digunakan untuk membuat komponen yang tidak murni.



▍Komponen Presentasi



Pertimbangkan fitur-fitur komponen presentasi:



  • Mereka tidak berinteraksi dengan sumber daya jaringan.
  • Mereka tidak menyimpan data ke localStorageatau memuat dari sana.
  • Mereka tidak memberikan beberapa data yang tidak dapat diprediksi.
  • Mereka tidak merujuk langsung ke waktu sistem saat ini (misalnya, dengan memanggil metode Date.now()).
  • Mereka tidak berinteraksi langsung dengan penyimpanan status aplikasi.
  • - , , , .


Karena item terakhir dalam daftar ini yang saya sebutkan, ketika berbicara tentang komponen presentasi, ini sebagian besar adalah komponen murni. Komponen ini membaca statusnya dari status React global. Oleh karena itu, seperti hook useStatedan useReducermenyediakan mereka dengan data implisit tertentu (yaitu - data yang tidak dijelaskan dalam fungsi tanda tangan) yang, dari sudut pandang teknis, tidak dapat memanggil komponen tersebut "bersih". Jika Anda membutuhkannya agar benar-benar bersih, Anda dapat mendelegasikan semua tugas pengelolaan status ke komponen kontainer, tetapi saya kira Anda tidak boleh melakukan ini, setidaknya sampai operasi komponen yang benar dapat diverifikasi menggunakan modul tes.



Musuh kebaikan.



Voltaire




▍Komponen Kontainer



Komponen wadah adalah komponen yang bertanggung jawab untuk mengelola status, melakukan operasi I / O, atau tugas lain yang mungkin merupakan efek samping. Mereka tidak perlu membuat markup apa pun sendiri. Sebaliknya, mereka mendelegasikan tugas rendering ke komponen presentasi, dan mereka sendiri berfungsi sebagai pembungkus untuk komponen tersebut. Biasanya, komponen kontainer dalam aplikasi React + Redux hanya memanggil mapStateToProps()dan mapDispatchToProps()kemudian meneruskan data yang sesuai ke komponen presentasi. Container juga dapat digunakan untuk beberapa tugas umum, yang akan kita bahas di bawah.



Komponen tingkat tinggi



A Higher Order Component (HOC) adalah komponen yang mengambil komponen lain dan mengembalikan komponen baru yang mengimplementasikan fungsionalitas baru berdasarkan komponen asli.



Komponen tingkat tinggi berfungsi dengan membungkus beberapa komponen dengan yang lain. Komponen pembungkus dapat mengimplementasikan beberapa logika dan membuat elemen DOM. Ini mungkin atau mungkin tidak meneruskan props tambahan ke komponen yang dibungkus.



Tidak seperti React hooks dan render props, komponen tingkat tinggi cocok untuk komposisi menggunakan pendekatan standar pada komposisi fungsi. Hal ini memungkinkan Anda untuk mendeskripsikan secara deklaratif hasil komposisi kemampuan yang dimaksudkan untuk digunakan di berbagai tempat aplikasi. Pada saat yang sama, komponen yang sudah jadi tidak boleh menyadari adanya kemungkinan tertentu. Berikut adalah contoh HOC dari EricElliottJS.com :



import { compose } from 'lodash/fp';
import withFeatures from './with-features';
import withEnv from './with-env';
import withLoader from './with-loader';
import withCoupon from './with-coupon';
import withLayout from './with-layout';
import withAuth from './with-auth';
import { withRouter } from 'next/router';
import withMagicLink from '../features/ethereum-authentication/with-magic-link';

export default compose(
  withEnv,
  withAuth,
  withLoader,
  withLayout({ showFooter: true }),
  withFeatures,
  withRouter,
  withCoupon,
  withMagicLink,
);


Yang ditampilkan di sini adalah campuran dari banyak fitur yang dibagikan di semua halaman di situs. Yakni, ia withEnvmembaca pengaturan dari variabel lingkungan, withAuthmengimplementasikan mekanisme otentikasi GitHub, withLoadermenampilkan animasi saat memuat data pengguna, , withLayout({ showFooter: true })menampilkan tata letak standar dengan footer, withFeaturemenampilkan pengaturan, withRoutermemuat router, withCouponbertanggung jawab untuk bekerja dengan kupon, dan withMagicLingmendukung otentikasi pengguna tanpa menggunakan kata sandi. Sihir .



Ngomong-ngomong, mengingat otentikasi kata sandi sudah usang dan praktik yang berbahaya, ada baiknya menggunakan metode otentikasi pengguna lain hari ini.



Hampir semua halaman di situs tersebut memanfaatkan semua fitur ini. Mempertimbangkan bahwa mereka disusun melalui komponen tingkat tinggi, Anda dapat memasukkan semuanya dalam komponen kontainer hanya dengan satu baris kode. Misalnya, begini tampilannya untuk halaman tutorial:



import LessonPage from '../features/lesson-pages/lesson-page.js';
import pageHOC from '../hocs/page-hoc.js';
export default pageHOC(LessonPage);


Komponen tingkat tinggi ini memiliki alternatif, tetapi ini adalah konstruksi meragukan yang disebut "piramida malapetaka" dan sebaiknya tidak digunakan. Beginilah tampilannya:



import FeatureProvider from '../providers/feature-provider';
import EnvProvider from '../providers/env-provider';
import LoaderProvider from '../providers/loader-provider';
import CouponProvider from '../providers/coupon-provider';
import LayoutProvider from '../providers/layout-provider';
import AuthProvider from '../providers/auth-provider';
import RouterProvider from '../providers/RouterProvider';
import MagicLinkProvider from '../providers/magic-link-provider';
import PageComponent from './page-container';

const WrappedComponent = (...props) => (
  <EnvProvider { ...props }>
    <AuthProvider>
      <LoaderProvider>
        <LayoutProvider showFooter={ true }>
          <FeatureProvider>
            <RouterProvider>
              <CouponProvider>
                <MagicLinkProvider>
                  <YourPageComponent />
                </MagicLinkProvider>
              </CouponProvider>
            </RouterProvider>
          </FeatureProvider>
        </LayoutProvider>
      </LoaderProvider>
    </AuthProvider>
  </EnvProvider>
);


Dan ini harus diulangi di setiap halaman. Dan jika sesuatu perlu diubah dalam struktur ini, maka perubahan harus dilakukan di mana pun itu ada. Saya pikir kerugian dari pendekatan ini cukup jelas.



Menggunakan komposisi untuk memecahkan masalah umum adalah salah satu cara terbaik untuk mengurangi kerumitan kode aplikasi Anda. Komposisi sangat penting sehingga saya bahkan menulis buku tentangnya .



Hasil



  • Mengapa React? React memberi kita rendering deterministik dari representasi visual komponen berdasarkan pengikatan data searah dan status komponen yang tidak dapat diubah.
  • JSX memungkinkan kita dengan mudah mendeskripsikan antarmuka dalam kode JavaScript.
  • - .
  • . , . , DOM DOM.
  • React , . , , .
  • - . - .
  • , . ( , ).


?



Dalam posting React ini, kami telah membahas banyak konsep pemrograman fungsional. Jika Anda berjuang untuk pemahaman yang mendalam tentang prinsip-prinsip pengembangan aplikasi React, akan berguna bagi Anda untuk memoles pengetahuan Anda tentang fungsi murni , tentang kekekalan , tentang kari dan penerapan sebagian fungsi, tentang komposisi fungsi. Anda dapat menemukan materi terkait di EricElliottJS.com .



Saya merekomendasikan penggunaan React bersama dengan Redux , Redux-Saga, dan RITEway . Redux direkomendasikan untuk digunakan dengan Autodux dan Immer... Untuk mengatur skema status yang kompleks, Anda dapat mencoba menggunakan Redux-DSM .



Saat Anda memahami dasar-dasarnya dan siap membuat aplikasi React yang sebenarnya, lihat Next.js dan Vercel . Alat-alat ini akan membantu mengotomatiskan konfigurasi sistem pembangunan proyek dan pipeline CI / CD, dengan bantuan mereka Anda dapat mempersiapkan proyek untuk penerapan yang dioptimalkan di server. Mereka memiliki efek yang sama seperti seluruh tim DevOps, tetapi mereka sepenuhnya gratis untuk digunakan.



Alat bantu apa yang Anda gunakan saat mengembangkan aplikasi React?










All Articles