Contents
Pengantar Stateful Component
Sebelumnya, kita sudah mempelajari props yang dapat mengirimkan data kepada child component dari parent component. Perlu kami tekankan bahwa props adalah “read-only” data yang immutable alias tidak untuk diubah nilainya.
UI dari sebuah aplikasi bersifat dinamis dan seringkali berubah seiring terjadinya interaksi oleh pengguna. Contoh paling sederhana adalah ketika Anda memberikan rating pada aplikasi toko online. Data rating diharapkan selalu berubah ketika terdapat interaksi dari pengguna.
Data di dalam komponen yang bertugas untuk menampung perubahan bukanlah props, melainkan state. Di modul ini, Anda akan belajar bagaimana membuat dan mengelola state agar UI yang dihasilkan oleh component dapat bersifat reaktif ketika terjadi perubahan data.
Tujuan dari modul ini adalah sebagai berikut.
- Membuat React component menggunakan sintaksis class (class component).
- Membuat dan mengelola state di dalam class component.
- Menangani sebuah event pada React component.
- Memahami Controlled Element dalam membuat form input.
- Melengkapi fungsionalitas dari aplikasi “Buku Kontak”.
Class Component
Di modul sebelumnya, Anda sudah belajar bahwa React component dibuat melalui sebuah fungsi. Namun, selain hanya fungsi, React component juga dapat dibuat menggunakan sintaksis class. Component yang dibuat menggunakan fungsi sering disebut dengan functional component, sedangkan component yang dibuat oleh class disebut dengan class component.
// class component import React from 'react'; class MyComponent extends React.Component { render() { const { name } = this.props; return ( <div> <p>Hello, {name}!</p> </div> ); } }
// functional component import React from 'react'; function MyComponent({ name }) { return ( <div> <p>Hello, {name}!</p> </div> ); }
Perbedaan paling mendasar antara class component dan functional component adalah benefit yang didapatkan. Maksudnya, ketika Anda membuat component dengan class, React secara default menawarkan fitur state dan lifecycle yang dapat Anda manfaatkan. Itulah sebabnya component yang dibuat menggunakan class bersifat stateful atau disebut dengan “stateful” component, sedangkan component yang dibangun menggunakan function bersifat stateless karena tidak dapat memanfaatkan state. Functional component hanya memanfaatkan props sebagai data dalam menampilkan UI.
Walaupun terdengar memiliki banyak benefit, mohon untuk tidak membuat class component secara berlebihan karena pembuatan class component lebih “mahal” daripada functional component. Dari cara pembuatannya saja class component membutuhkan banyak sintaksis dibandingkan dengan functional component. Jika Anda tidak berniat untuk memanfaatkan salah satu benefit yang ditawarkan, sebaiknya tetap gunakan functional component daripada class component.
Sejarah Perkembangan React Component
Saat ini Anda sudah mengetahui bahwa component dapat dibuat dengan dua cara. Namun, tahukah Anda bahwa pembuatan component di React memiliki cerita yang cukup panjang?
Pada versi awal (initial public release), hanya ada satu cara dalam membuat React component, yakni menggunakan fungsi React.createClass yang tampak seperti ini.
const MyComponent = createClass({ displayName: 'MyComponent', render() { const paragraph = React.createElement('p', null, 'Hello, ' + this.props.name); return React.createElement('div', null, paragraph); } });
Component yang dibuat menggunakan React.createClass memiliki method render. Method tersebut mendeskripsikan React element yang akan dikembalikan dan di-render. Tujuan dari membuat komponen masih sama ini yaitu membuat UI yang reusable untuk ditampilkan.
Catatan: penggunaan React.createClass sudah deprecated (kedaluwarsa) dan tidak bisa digunakan lagi semenjak React versi 16. Jika Anda masih ingin menggunakannya, pasanglah package create-react-class secara terpisah.
Selanjutnya, ketika sintaksis class telah hadir di JavaScript (ES6), React mengenalkan alternatif dalam membuat component penggunaan fungsi createClass, yakni dengan mewarisi class React.Component bergaya ES6 seperti ini.
class MyComponent extends React.Component { render() { const { name } = this.props; return ( <div> <p>Hello, {name}!</p> </div> ); } }
Pada versi 0.14.0, React memperkenalkan functional component alias component yang dibuat menggunakan function. Dengan adanya functional component, pembuatan component--yang bersifat stateless--jauh lebih simpel karena pembuatanya sama seperti fungsi JavaScript biasa.
function MyComponent({ name }) { return ( <div> <p>Hello, {name}!</p> </div> ); }
Latihan Membuat Class Component
Sekarang Anda tahu bahwa React component dapat dibuat melalui function (functional component) dan class (class component). Di modul sebelumnya, Anda sudah banyak praktik membuat functional component. Nah, pada latihan inilah kita akan belajar cara membuat class component.
Tujuannya dari latihan ini adalah memastikan Anda mampu membuat class component. Yap sampai di sana saja. Jadi kita akan buat component sederhana dulu. Yuk, kita mulai!
-
Buka tautan dicoding-react-starter atau Anda juga boleh membuat proyek react baru secara lokal menggunakan CRA.
-
Silakan buat class component bernama MyComponent pada berkas index.js dan render komponennya pada DOM. Caranya, silakan tulis kode berikut.
import React from 'react'; import { createRoot } from 'react-dom/client'; class MyComponent extends React.Component { render() { return <p>Hello, class component!</p>; } } const root = createRoot(document.getElementById('root')); root.render(<MyComponent />);
Ingat, ya! Class component dibuat menggunakan sintaksis class dan mewarisi (extends) React.Component. Seluruh class yang mewarisi React.Componentwajib memiliki fungsi render untuk mengembalikan UI (React element) yang akan ditampilkan.
Kode di atas akan menghasilkan tampilan berikut.
-
Sekarang, mari kita beri nilai properti name pada MyComponent..
import React from 'react'; import { createRoot } from 'react-dom/client'; class MyComponent extends React.Component { render() { return <p>Hello, {this.props.name}!</p>; } } const root = createRoot(document.getElementById('root')); root.render(<MyComponent name="Dicoding" />);
Berbeda dari functional component, di class component Anda bisa mengakses nilai properti melalui this.props. Karena this pada class component bernilai instance dari component itu sendiri, Anda bisa mengakses props. Berikut output dari console.log(this) di dalam fungsi render.
Catatan: Mungkin Anda penasaran apa isi dari nilai this pada functional component? Functional component tidak memiliki this-nya sendiri, jadi nilainya akan mengacu ke objek global yaitu window (jika component di-render pada DOM). Jadi Anda tidak bisa mengakses props melalui this.props pada functional component.
Oke, simpan perubahan kode dan sekarang UI tampak seperti ini.
-
Karena class component sejatinya adalah class, kita dapat memanfaatkan constructor untuk menginisialisasi data--contohnya state--atau menuliskan kode yang akan dipanggil setiap kali pembuatan component.
import React from 'react'; import { createRoot } from 'react-dom/client'; class MyComponent extends React.Component { constructor(props) { super(props); console.log('Component created!'); } render() { return <p>Hello, {this.props.name}!</p>; } } const root = createRoot(document.getElementById('root')); root.render(<MyComponent name="Dicoding" />);
Ketika Anda memanfaatkan constructor, pastikan selalu memanggil base constructor (super) dan berikan nilai props. Jika tidak, nilai this.props pada component akan bernilai undefined. Hal ini penting untuk Anda catat, ya!
Sekarang, setiap kali kita menggunakan MyComponent, ia akan menampilkan output “Component created!”.
root.render( <div> <MyComponent name="Dicoding" /> <MyComponent name="John" /> <MyComponent name="Doe" /> </div> );
Berikut hasilnya.
State Component
Data merupakan hal yang membuat React component menjadi hidup. Bayangkan saja jika pada proyek contact-app tidak ada array yang menampung data contacts, tentu aplikasi menjadi tidak berguna karena tidak dapat menampilkan apa pun. Selain itu, data di dalam komponen diharapkan dapat berubah. Perubahan biasanya terjadi ketika ada interaksi atau input yang dilakukan pengguna. Interaksi bisa seperti menekan tombol tambah atau hapus kontak.
Untuk memahami pengelolaan data di dalam komponen React, yuk simak gambar di bawah ini.
Alat di atas (mari kita sebut counter) sering Anda temukan ketika hendak masuk ke gerbang wisata, karena memang counter digunakan untuk menghitung pengunjung yang datang. Menariknya, cara kerja komponen React dengan alat tersebut dapat dibilang mirip. Mengapa bisa demikian?
Counter menampilkan data berupa angka jumlah pengunjung yang datang pada saat itu. Biasanya tombol putih ditekan bila ada pengunjung baru, kemudian layar counter secara reaktif akan memperbarui tampilannya dengan data terbaru (jumlah sebelumnya +1). Di akhir hari (misalnya), petugas selalu menekan/memutar tombol hitam untuk mereset kembali datanya agar dapat digunakan kembali di hari berikutnya. Ingat! Data pada counter tidak akan berubah bila tidak ada aksi yang dilakukan pengguna (seperti menekan tombol tambah atau reset).
React component memiliki cara kerja yang sama seperti counter dalam mengelola data. Di dalam React component, kita bisa menyimpan sebuah data yang bila berubah bisa memicu perubahan pada tampilan UI. Syaratnya, data tersebut perlu disimpan pada tempat khusus dinamakan state.
Meskipun state dan props dapat menyimpan data, tetapi keduanya hal yang berbeda. Data di dalam props berasal dari luar komponen dan diharapkan tidak berubah, sedangkan data di dalam state perlu diinisialisasi di dalam komponen itu sendiri dan datanya boleh berubah.
Di materi sebelumnya, Anda sudah tahu bahwa untuk memanfaatkan state, kita harus membuat class component. State di dalam class component dapat diakses melalui properti this.state dan datanya diinisialisasi di dalam constructor.
import React from 'react'; class Counter extends React.Component { constructor(props) { super(props); // inisialisasi data dalam state this.state = { count: 0 }; } render() { return ( <div> {/* menampilkan data count */} <p>{this.state.count}</p> </div> ); } }
Perubahan data yang disimpan di dalam this.state akan memicu pemanggilan fungsi render() pada class component, itulah kunci mengapa UI selalu menampilkan data terbaru. Namun, untuk mencapai tujuan tersebut, data di dalam state harus diubah melalui fungsi this.setState(), bukan melalui properti this.state secara langsung.
// Correct! this.setState((previousState) => { return { count: previousState.count + 1, } });
// Don't! this.state.count = this.state.count + 1;
Mari kita bahas fungsi setState() lebih dalam.
this.setState() atau setState() merupakan fungsi yang digunakan khusus untuk mengubah nilai state di dalam class component. Fungsi inilah yang sebenarnya memicu pemanggilan fungsi render() ketika data di dalam state berubah. Fungsi setState() dapat menerima dua tipe parameter, yaitu objek dan fungsi yang mengembalikan objek.
// parameter berupa objek // reset the count value this.setState({ count: 0 });
// parameter berupa fungsi // increase the count value this.setState((previousState) => { return { count: previousState.count + 1 } });
Nilai yang objek diberikan--atau yang dikembalikan oleh fungsi--akan menjadi nilai state yang baru untuk menggantikan objek state lama. Namun, dalam memperbarui state yang baru, fungsi this.setState() menggunakan teknik "menggabungkan" bukan mengganti keseluruhan nilai state.
Catatan: Jika komponen memiliki state { name: 'john', surename: 'doe' }, ketika Anda mengubah state dengan this.setState({ name: 'jane' }), nilai state surename tidak akan hilang dan tetap bernilai 'doe'.
Anda bisa memberikan parameter berupa objek (cara pertama) ketika ingin menetapkan nilai state tanpa memperhatikan nilai state yang ada sebelumnya. Contoh pada kasus counter, penggunaan ini dapat diimplementasikan ketika Anda ingin mereset nilai dari data count. Ketika mereset tentu kita tidak perlu memperhatikan atau mengetahui data sebelumnya ‘kan? Cukup berikan nilai baru, yakni 0.
Untuk parameter berupa fungsi (cara kedua), penggunaan ini cocok ketika Anda ingin menetapkan nilai state yang bergantung pada nilai state sebelumnya. Contohnya, ketika ingin menambahkan 1 nilai pada data counter, tentu Anda membutuhkan nilai yang sebelumnya, bukan? Anda bisa memanfaatkan previousState untuk melakukan hal itu.
Walaupun cara pertama terkesan lebih ringkas, tetapi secara pribadi penulis lebih suka menggunakan cara kedua dalam memanggil fungsi setState(). Mengapa demikian? Karena cara kedua dapat diterapkan pada kasus apa pun. Jika Anda tidak butuh nilai previousState, sebenarnya Anda tidak perlu menuliskan parameter tersebut 'kan?
Namun, sebenarnya pemilihan tersebut kembali lagi ke preferensi pribadi. Jika Anda merasa nyaman menggunakan cara pertama, go ahead! Kedua cara tersebut sama saja dan tidak ada pengaruhnya terhadap performa atau menyebabkan bug pada aplikasi. Aman!
Rekap
Dengan membuat komponen yang mengelola state di dalamnya, setiap kali ada perubahan pada state tersebut, React akan mengetahui dan secara otomatis membuat pembaruan pada UI. Ini adalah keuntungan besar ketika menggunakan React untuk membangun UI. Ketika kita perlu memperbarui tampilan, cukup perbarui state saja. Kita tidak perlu melacak secara presisi bagian mana yang perlu di-update, biarkan React yang melakukannya berdasarkan state terbaru. Sederhana, bukan?
Catatan: Proses menentukkan apa yang telah berubah di output baru dari output sebelumnya dinamakan dengan Reconciliation.
Lalu, kapan dan di mana kita harus memanggil fungsi setState() untuk memperbarui state? Jawabannya ketika terjadi interaksi dari pengguna. Untuk menangkap interaksi pengguna pada React component, Anda perlu belajar dulu bagaimana cara Event Handling bekerja pada React. Kita akan bahas mengenai itu di materi selanjutnya.
Sebelumnya : Membuat Aplikasi Daftar Kontak | Selanjutnya : Event Handling |
0 Komentar