Mengoper Props ke Komponen
Komponen React menggunakan props untuk berkomunikasi antara satu dengan yang lainnya. Setiap komponen induk bisa mengirim beberapa informasi pada komponen-komponen anaknya dengan memberikan mereka props. Props mungkin akan mengingatkan Anda dengan atribut HTML, namun Anda bisa mengirim nilai JavaScript apa pun melalui itu, termasuk objek, senarai, bahkan fungsi.
Anda akan mempelajari
- Bagaimana cara mengoper props ke komponen
- Bagaimana cara membaca props dari komponen
- Bagaimana cara memberi nilai bawaan untuk props
- Bagaimana cara mengirim beberapa JSX ke dalam component
- Bagaimana props berubah seiring waktu
Props umum
Props adalah informasi yang Anda kirimkan pada tag JSX. Sebagai contoh, className
, src
, alt
, width
, dan height
adalah beberapa contoh dari props yang bisa Anda kirimkan pada <img>
:
function Avatar() { return ( <img className="avatar" src="https://i.imgur.com/1bX5QH6.jpg" alt="Lin Lanying" width={100} height={100} /> ); } export default function Profile() { return ( <Avatar /> ); }
Props yang bisa dikirimkan pada tag <img>
sudah didefinisikan sebelumnya (ReactDOM menyesuaikan dengan standar HTML). Namun Anda bisa mengirimkan props apa pun pada komponen Anda sendiri, Misalnya <Avatar>
, untuk dikustomisasi. Begini caranya!
Mengoper props ke komponen
Pada kode ini, komponen Profile
tidak mengirimkan props apa pun pada komponen anaknya, yaitu Avatar
:
export default function Profile() {
return (
<Avatar />
);
}
Anda bisa memberi Avatar
beberapa props dalam dua langkah.
Langkah 1: Mengoper props ke komponen anak
Pertama-tama, kirimkan beberapa props pada Avatar
. Sebagai contoh, mari kirimkan dua props: person
(sebuah objek), dan size
(sebuah angka):
export default function Profile() {
return (
<Avatar
person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
size={100}
/>
);
}
Sekarang Anda bisa membaca props tersebut di dalam komponen Avatar
.
Langkah 2: Membaca props di dalam komponen anak
Anda bisa membaca props tersebut dengan mendaftarkan namanya yaitu person, size
dengan cara dipisahkan dengan koma di dalam ({
dan })
langsung setelah function Avatar
. Hal ini memungkinkan Anda untuk menggunakannya di dalam kode Avatar
, sama halnya saat Anda menggunakan variabel.
function Avatar({ person, size }) {
// sekarang person dan size bisa Anda pakai di sini
}
Tambahkan beberapa logika pada Avatar
yang menggunakan props person
dan size
untuk di-render, dan selesai.
Sekarang Anda bisa membuat Avatar
untuk di-render dalam banyak cara dan dengan props yang berbeda. Cobalah utak-atik nilainya!
import { getImageUrl } from './utils.js'; function Avatar({ person, size }) { return ( <img className="avatar" src={getImageUrl(person)} alt={person.name} width={size} height={size} /> ); } export default function Profile() { return ( <div> <Avatar size={100} person={{ name: 'Katsuko Saruhashi', imageId: 'YfeOqp2' }} /> <Avatar size={80} person={{ name: 'Aklilu Lemma', imageId: 'OKS67lh' }} /> <Avatar size={50} person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }} /> </div> ); }
Props membuat Anda berpikir tentang komponen induk dan komponen anak secara terpisah. Sebagai contoh, Anda bisa mengubah props person
atau size
di dalam Profile
tanpa perlu memikirkan bagaimana Avatar
menggunakannya. Begitupun, Anda bisa mengubah bagaimana Avatar
menggunakan props tersebut, tanpa menghiraukan Profile
.
Anda bisa menganggap props seperti “kenop” yang bisa disesuaikan. Props berperan sama seperti arguments pada functions—Nyatanya, props adalah satu-satunya argument pada komponen Anda! Komponen fungsi React menerima satu argument, sebuah objek props.:
function Avatar(props) {
let person = props.person;
let size = props.size;
// ...
}
Biasanya Anda tidak memerlukan objek props secara utuh, maka Anda memecahnya menjadi props tersendiri.
Menentukan nilai bawaaan untuk prop
Jika Anda ingin memberi prop nilai bawaan untuk berjaga-jaga saat tidak ada nilai yang ditentukan, Anda bisa melakukannya dengan destructring lalu menaruh =
dan nilai bawaannya tepat setelah parameter:
function Avatar({ person, size = 100 }) {
// ...
}
Sekarang, jika <Avatar person={...} />
di-render tanpa menerima prop size
, size
akan bernilai 100
.
Nilai bawaan hanya akan terpakai jika prop size
tidak ada atau jika Anda mengirim size={undefined}
. Namun jika Anda mengirim size={null}
atau size={0}
, nilai bawaan tidak akan terpakai.
Meneruskan props dengan sintaksis spread JSX
Terkadang, mengirim props bisa sangat repetitif:
function Profile({ person, size, isSepia, thickBorder }) {
return (
<div className="card">
<Avatar
person={person}
size={size}
isSepia={isSepia}
thickBorder={thickBorder}
/>
</div>
);
}
Tidak ada salahnya dengan kode yang repetitif—itu membuatnya lebih mudah untuk dibaca. Namun terkadang Anda mungkin lebih menyukai keringkasan. Beberapa komponen meneruskan semua propsnya kepada komponen anaknya, persis seperti yang Profile
lakukan dengan Avatar
. Karena mereka tidak menggunakan propsnya secara langsung, ini akan masuk akal untuk menggunakan sintaksis ”spread” yang mana lebih ringkas:
function Profile(props) {
return (
<div className="card">
<Avatar {...props} />
</div>
);
}
Ini akan meneruskan semua props milik Profile
pada Avatar
tanpa menuliskannya satu-persatu.
Gunakan sintaksis spread dengan batasan. Jika Anda menggunakannya pada setiap komponen, maka ada yang salah. Seringkali, ini menunjukan bahwa Anda perlu memecah komponen Anda dan mengirim anaknya sebagai JSX. Mari kita bahas!
Mengoper JSX sebagai anak
Sudah umum untuk menyisipkan tag bawaan pada peramban:
<div>
<img />
</div>
Terkadang Anda ingin menyisipkan komponen Anda dengan cara yang sama:
<Card>
<Avatar />
</Card>
Saat Anda menyisipkan konten ke dalam tag JSX, komponen induk akan menerima konten tersebut dalam bentuk prop yang disebut children
. Sebagai contoh, Komponen Card
di bawah akan menerima prop children
yang diisi <Avatar />
lalu me-rendernya dengan cara membungkusnya ke dalam div:
import Avatar from './Avatar.js'; function Card({ children }) { return ( <div className="card"> {children} </div> ); } export default function Profile() { return ( <Card> <Avatar size={100} person={{ name: 'Katsuko Saruhashi', imageId: 'YfeOqp2' }} /> </Card> ); }
Cobalah ubah <Avatar>
yang ada di dalam <Card>
dengan teks untuk melihat bagaimana komponen Card
bisa disisipkan konten apa pun. Komponen tersebut tidak perlu “mengetahui” apa yang di-render di dalamnya. Anda lihat betapa fleksibelnya hal ini.
Anda bisa menganggap bahwa komponen dengan prop children
itu mempunyai “lubang” yang bisa “diisi” oleh komponen induknya dengan JSX secara bebas. Anda akan sering menggunakan prop children
sebagai pembungkus: panels, grids, dan lainnya.
Ilustrasi oleh Rachel Lee Nabors
Bagaimana props berubah seiring waktu
Komponen Clock
di bawah menerima dua props dari komponen induknya: color
dan time
. (Kode untuk komponen induknya dihilangkan karena itu menggunakan state, yang mana belum kita bahas untuk saat ini.)
Coba ubahlah warna pada kotak pilihan di bawah:
export default function Clock({ color, time }) { return ( <h1 style={{ color: color }}> {time} </h1> ); }
Contoh ini menggambarkan bahwa sebuah komponen mungkin menerima props yang berbeda seiring waktu. Props tidak selalu bersifat tetap! Begini, prop time
berubah setiap detik, dan prop color
berubah ketika Anda memilih warna lain. Data pada komponen akan ditampilkan props kapan saja, bukan hanya di awal.
Bagaimanapun, props bersifat immutable—Sebuah istilah pada ilmu komputer yang berarti “tidak dapat diubah”. Saat sebuah komponen ingin mengubah propsnya (sebagai contoh, untuk merespon interaksi pengguna atau merespon data baru), mereka harus “meminta” komponen induknya untuk mengirim dirinya props yang lain—objek baru! Lalu props yang lama akan disingkirkan, dan nantinya mesin JavasCript akan mengambil kembali memori yang dipakai oleh mereka.
Jangan mencoba untuk “mengubah props“. Ketika Anda perlu merespon masukan pengguna (misalnya mengubah warna yang dipilih), Anda akan memerlukan ”set state”, yang mana akan Anda pelajari pada State: Memori Milik Komponen.
Rekap
- Untuk mengoper props, tambahkan langsung ke JSX, seperti yang Anda lakukan dengan atribut HTML.
- Untuk membaca props, gunakan
function Avatar({ person, size })
sintaksis destructuring. - Anda bisa memberi nilai bawaan seperti
size = 100
, yang mana akan digunakan untuk props yang kosong danundefined
. - Anda bisa meneruskan semua props dengan
<Avatar {...props} />
sintaksis spread JSX, Namun jangan terlalu sering menggunakannya! - Menyisipkan JSX seperti
<Card><Avatar /></Card>
akan menghasilkan propchildren
milik komponenCard
. - Props hanya untuk dibaca pada satu waktu: setiap render menghasilkan props yang baru.
- Anda tidak bisa mengubah props. Saat Anda butuh interaktivitas, Anda akan membutuhkan state.
Tantangan 1 dari 3: Mengekstrak komponen
Komponen Gallery
ini berisi dua markup yang sama persis. Ekstraklah menjadi komponen Profile
untuk mengurangi duplikasi. Anda perlu memilih props apa saja yang akan dikirimkan.
import { getImageUrl } from './utils.js'; export default function Gallery() { return ( <div> <h1>Notable Scientists</h1> <section className="profile"> <h2>Maria Skłodowska-Curie</h2> <img className="avatar" src={getImageUrl('szV5sdG')} alt="Maria Skłodowska-Curie" width={70} height={70} /> <ul> <li> <b>Profesi: </b> Fisikawan dan kimiawan </li> <li> <b>Penghargaan: 4 </b> (Penghargaan Nobel Fisika, Penghargaan Nobel Kimia, Medali Davy, Medali Matteucci) </li> <li> <b>Telah Menemukan: </b> polonium (unsur kimia) </li> </ul> </section> <section className="profile"> <h2>Katsuko Saruhashi</h2> <img className="avatar" src={getImageUrl('YfeOqp2')} alt="Katsuko Saruhashi" width={70} height={70} /> <ul> <li> <b>Profesi: </b> Ahli Geokimia </li> <li> <b>Penghargaan: 2 </b> (Penghargaan Miyake Geokimia, Penghargaan Tanaka) </li> <li> <b>Telah Menemukan: </b> sebuah metode untuk mengukur karbon dioksida pada air laut </li> </ul> </section> </div> ); }