Terakhir diperbarui: 2024-02-26

Components, JSX, dan Props

Konsep dalam penggunaan ReactJS untuk antarmuka pengguna ada beberapa yang penting, diantaranya tentang komponen, JavaScript XML (JSX), membuat component dan penggunaan props.

Pengetahun yang Anda harus miliki

Sebelum memulai codelab ini, sebaiknya Anda memiliki pengetahuan dasar tentang:

Apa yang Anda akan pelajari

Apa yang Anda perlu persiapkan

Komponen merupakan salah satu konsep inti dari React. Komponen adalah pondasi di mana Anda bangun antarmuka pengguna (UI). Anda dapat membayangkan komponen sebagai balok-balok lego yang menyusun UI. Di dalam web, HTML memungkinkan kita membuat dokumen-dokumen terstruktur yang kaya dengan kumpulan tag bawaannya seperti h1 dan li seperti berikut ini:

<article>
  <h1>Komponen Pertama Saya</h1>
  <ol>
    <li>Komponen: Pembangun Balok UI</li>
    <li>Mendefinisikan suatu Komponen</li>
    <li>Menggunakan suatu Komponen</li>
  </ol>
</article>

Markup ini merepresentasikan artikel article, heading h1 dan daftar isi (yang disingkat) sebagai daftar yang tersusun ol. Markup seperti ini, digabung dengan CSS untuk style, dan JavaScript untuk interaktivitas, berada di belakang setiap sidebar, avatar, modal, dropdown—setiap potongan UI yang Anda liat di dalam web.

React memungkinkan Anda menggabung markup, CSS, dan JavaScript Anda menjadi "komponen" yang dibuat khusus, elemen UI yang dapat digunakan kembali untuk aplikasi Anda. Daftar isi yang Anda lihat di atas dapat diubah menjadi sebuah komponen TableOfContents yang dapat Anda render pada setiap halaman. Dari belakang, itu tetap menggunakan tag HTML yang sama seperti article, h1, dan lain-lain.

Sama seperti tag HTML, Anda dapat menggabung, mengurut, dan menyusun bertingkat komponen untuk mendesain halaman penuh. Misalnya, halaman yang terdapat komponen-komponen React seperti berikut ini:

<PageLayout>
  <NavigationHeader>
    <SearchBar />
    <Link to="/docs">Docs</Link>
  </NavigationHeader>
  <Sidebar />
  <PageContent>
    <TableOfContents />
    <DocumentationText />
  </PageContent>
</PageLayout>

Seiring berkembangnya proyek, Anda dapat memperhatikan bahwa banyak desain yang bisa dikomposisi dengan menggunakan ulang komponen-komponen yang sudah Anda buat, mempercepat pengembangan proyek Anda. Daftar isi di atas bisa disertakan pada layar apa pun dengan TableOfContents. Anda bisa memulai proyek dengan cepat menggunakan ribuan komponen-komponen siap pakai yang dibagi oleh komunitas open source React seperti Chakra UI dan Material UI.

Setelah dari codelab atau pertemuan kedua, Anda telah mulai membuat project pertama. Selesaikan langkah-langkah praktikum berikut ini menggunakan editor Visual Studio Code (VS Code) atau code editor lain kesukaan Anda. Jawablah di laporan praktikum Anda pada setiap soal yang ada di beberapa langkah praktikum ini.

Langkah 1: Buat Folder Baru

Buatlah folder baru bernama 03-belajar-komponen lalu di dalam folder tersebut, jalankan terminal dengan mengetikkan perintah berikut:

npx create-next-app

Langkah 2: Buat Komponen Baru

Buatlah folder baru dan file baru di src/components/profile.tsx lalu ketik kode berikut ini.

import Image from "next/image";

export default function Profile() {
    return (
      <Image
        src="https://i.imgur.com/MK3eW3Am.jpg"
        alt="Katherine Johnson"
        width={100}
        height={100}
        style={{
          maxWidth: "100%",
          height: "auto",
          margin: "13px"
        }}
      />
    );
  }

Kode tersebut menggunakan komponen Image bawaan dari Next.js.

Langkah 3: Import Komponen

Lakukan import komponen Profile ke src/app/page.tsx

import Profile from "../components/profile";

Menyusun secara bertingkat dan mengorganisir komponen

Komponen adalah fungsi JavaScript biasa, sehingga Anda bisa menjaga beberapa komponen di dalam file yang sama. Ini nyaman ketika komponen-komponen relatif kecil atau saling terkait secara erat. Jika file ini mulai memiliki sangat banyak komponen, Anda bisa memindahkan komponen Profile ke suatu file yang berbeda. Anda akan belajar bagaimana cara melakukan ini segera pada bagian codelab ini berikutnya.

Karena komponen-komponen Profile di-render di dalam Gallery—bahkan beberapa kali!—kita dapat mengatakan bahwa Gallery adalah sebuah komponen induk, yang me-render setiap Profile sebagai sebuah "anak". Ini merupakan bagian ajaib dari React: Anda bisa mendefinisikan suatu komponen sekali, kemudian digunakan di banyak tempat dan sebanyak yang Anda suka.

Keajaiban komponen terletak pada kemampuannya yang dapat digunakan kembali. Anda dapat membuat komponen yang disusun dengan komponen lain. Namun, ketika Anda menyusun komponen-komponen yang semakin banyak, seringkali lebih masuk akal untuk mulai membaginya ke dalam file-file yang berbeda. Dengan ini Anda menjaga file Anda agar tetap mudah dipindai dan digunakan kembali di banyak tempat.

Misalnya di dalam komponen Gallery terdapat banyak komponen Profile. Bagaimana jika Anda ingin mengubah landing screen di masa depan dan memasukkan daftar buku sains di sana? Atau meletakkan semua profil di tempat lain? Maka sebaiknya memindahkan komponen Gallery dan Profile dari file komponen root. Ini akan membuat lebih modular dan dapat digunakan kembali di file lain. Secara umum, Anda dapat memindahkan sebuah komponen dengan tiga langkah berikut ini:

  1. Buat sebuah file .js atau .tsx baru untuk memasukkan komponen. Sebaiknya semua komponen diletakkan dalam folder yang sama yaitu components.
  2. Ekspor function component Anda dari file tersebut (baik menggunakan default atau named eskpor).
  3. Impor dimana Anda akan menggunakan komponen tersebut (menggunakan teknik yang sesuai untuk mengimpor default atau named ekspor).

Default vs named ekspor

Ada dua cara utama untuk mengekspor nilai dengan JavaScript: default exports dan named exports. Sejauh ini, contoh kita hanya menggunakan default exports. Tapi Anda dapat menggunakan satu atau keduanya pada file yang sama. Sebuah file dapat menggunakan tidak lebih dari satu default export, tapi dapat menggunakan named exports sebanyak yang Anda suka.

Teknik untuk mengekspor komponen Anda harus sesuai dengan cara mengimpornya. Anda akan mendapatkan error jika Anda mencoba untuk mengimpor default exports dengan cara yang sama Anda menggunakan named exports. Tabel ini akan membantu Anda untuk memahaminya:

Sintaksis

Pernyataan Expor

Pernyataan Impor

Default

export default function Button() {}

import Button from './Button.js';

Named

export function Button() {}

import { Button } from './Button.js';

Ketika Anda menulis default imports, Anda dapat memberi nama apa saja setelah import. Contoh, Anda dapat menulis import Banana from './Button.js' dan itu akan tetap ketika Anda menggunakan export default yang sama. Sebaliknya, dengan named imports, nama harus sama di kedua sisi. Itulah mengapa disebut named imports!

Kebanyakan developer seringkali menggunakan default exports jika file yang diekspor hanya satu komponen, dan menggunakan named exports jika mengekspor beberapa komponen dan nilai. Bagaimanapun gaya koding yang Anda gunakan, selalu beri nama yang berarti pada fungsi komponen Anda dan isi file tersebut. Komponen tanpa nama, seperti export default ()=>{}, tidak disarankan karena membuat proses debug lebih sulit.

Selesaikan langkah-langkah praktikum berikut ini menggunakan editor Visual Studio Code (VS Code) atau code editor lain kesukaan Anda. Jawablah di laporan praktikum Anda pada setiap soal yang ada di beberapa langkah praktikum ini.

Langkah 1: Buat Komponen Baru

Buatlah file baru di src/components/gallery.tsx berisi kode seperti berikut:

import Profile from "./profile";

export function Gallery() {
    return (
        <div className="columns-3">
            <Profile />
            <Profile />
            <Profile />
        </div>
    );
}

Langkah 2: Impor Komponen

Lakukan impor komponen di src/app/page.tsx seperti berikut ini. Hapus kode komponen lama Profile, lalu sesuaikan dengan komponen baru Gallery yang telah dibuat.

import { Gallery } from "@/components/gallery";

...

Kenapa JSX ?

React menggunakan logika rendering UI yang menakjubkan secara bersamaan, diantaranya ketika event di-handle, perubahan state, dan penyiapan data untuk ditampilkan pada halaman web.

React tidak mewajibkan untuk menggunakan JSX, tetapi paling banyak digunakan oleh developer karena sangat membantu secara visual ketika bekerja dengan UI bersama kode JavaScript. Selain itu juga mendukung React untuk menunjukkan jika terjadi error dan pesan warning.

JSX adalah perpanjangan sintaksis untuk menulis kode seperti HTML dalam file JavaScript. Meskipun ada beberapa cara lain, JSX lebih dipilih oleh sebagian besar developer React dan codebase karena kepadatannya.

JSX: Meletakkan markup ke JavaScript

Website selama ini dibuat dari HTML, CSS, dan JavaScript. Selama bertahun-tahun, pengembang website menaruh konten di HTML, desain di CSS, dan logika di JavaScript—tidak jarang di file yang berbeda. Konten dibangun di HTML sedangkan logika halaman disimpan secara terpisah dalam JavaScript seperti kode berikut:

HTML

JavaScript

Namun, seiring dengan situs yang makin interaktif, logika semakin menentukan konten. JavaScript mengatur HTML, Inilah mengapa dalam React, logika render dan markup berada di satu tempat yang sama—komponen.

Menggabungkan logika render dan markup untuk sebuah tombol memastikan mereka tersinkronasi dengan satu sama lain pada tiap perubahan. Sebaliknya, detil yang tidak berhubungan, markup untuk tombol dan sidebar, juga tidak terhubung dengan satu sama lain, membuat perubahan masing-masing menjadi lebih aman.

Masing-masing komponen React adalah fungsi JavaScript yang bisa memiliki markup yang di-render oleh React ke peramban. Komponen React menggunakan ekstensi sitaksis yang bernama JSX untuk merepresentasikan markup tersebut. JSX terlihat sangat mirip dengan HTML, namun lebih ketat dan dapat menampilkan informasi secara dinamis. Cara terbaik untuk memahami JSX adalah dengan langsung mengubah beberapa markup HTML menjadi JSX.

Mengubah HTML menjadi JSX

Anggap anda memiliki HTML yang valid seperti kode berikut:

<h1>Daftar Tugas Putri</h1>
<img 
  src="https://i.imgur.com/yXOvdOSs.jpg" 
  alt="Putri" 
  class="photo"
>
<ul>
    <li>Mengerjakan PR
    <li>Pergi belanja
    <li>Minum vitamin
</ul>

Dan anda ingin meletakkannya di komponen:

export default function TodoList() {
  return (
    // ???
  )
}

Jika anda salin dan tempel secara langsung, maka dia tidak akan bekerja:

Ini dikarenakan JSX lebih ketat dan memiliki banyak peraturan dibandingkan HTML! Jika anda membaca pesan error yang tertera, pesan tersebut akan mengarahkanmu untuk memperbaiki markup, atau anda bisa mengikuti panduan berikut.

1. Hanya mengembalikan satu elemen

Untuk mengembalikan lebih dari satu elemen, bungkus mereka dengan satu tag parent.

Contohnya, anda dapat menggunakan tag div

<div>
  <h1>Daftar Tugas Putri</h1>
  <img 
    src="https://i.imgur.com/yXOvdOSs.jpg" 
    alt="Putri" 
    class="photo"
  >
  <ul>
    ...
  </ul>
</div>

Jika anda tidak ingin menambahkan div pada markup, anda dapat menggunakan tag kosong saja seperti berikut:

<>
  <h1>Daftar Tugas Putri</h1>
  <img 
    src="https://i.imgur.com/yXOvdOSs.jpg" 
    alt="Putri" 
    class="photo"
  >
  <ul>
    ...
  </ul>
</>

Tag kosong di atas disebut Fragment. Fragments dapat menggabungkan beberapa tag tanpa memasukkan tag tersebut ke bagian dari HTML.

2. Tutup semua tag

Semua tag JSX harus dapat ditutup tag tunggal seperti < img > harus ditulis < img />, dan tag ganda seperti < li > oranges harus ditulis < li > oranges < / li >.

Berikut adalah kode dan daftar tugas Putri dengan tag ganda:

<>
  <img 
    src="https://i.imgur.com/yXOvdOSs.jpg" 
    alt="Putri" 
    class="photo"
   />
  <ul>
    <li>Mengerjakan PR</li>
    <li>Pergi Belanja</li>
    <li>Minum vitamin</li>
  </ul>
</>

3. Ubah sebagian menjadi camelCase!

JSX berubah menjadi JavaScript dan atribut yang ditulis di JSX menjadi key pada objek di JavaScript. Dalam komponen, atribut akan lebih mudah dibaca sebagai variable. Namun JavaScript memiliki beberapa batasan dalam menamai variabel. Contohnya, nama variabel tidak boleh terdiri dari karakter minus dan tidak boleh menggunakan nama pesanan tertentu seperti class.

Inilah mengapa di React, banyak atribut HTML dan SVG ditulis secara camelCase. Contohnya, stroke-width dapat ditulis sebagai strokeWidth. Dan karena class merupakan nama pesanan, di React kita menulisnya sebagai className, dinamakan sesuai dengan versi DOM-nya:

<img 
  src="https://i.imgur.com/yXOvdOSs.jpg" 
  alt="Putri" 
  className="photo"
/>

Anda dapat mencari semua atribut pada list DOM component berikut. Jika ada yang salah, jangan takut—React akan menampilkan pesan dengan koreksi ke konsol browser.

Tip: Gunakan JSX Converter

Mengubah atribut di markup yang sudah ada bisa menjadi membosankan. Disarankan untuk menggunakan converter untuk mengubah HTML dan SVG-mu menjadi JSX. Konverter sangat berguna dalam praktiknya, namun tetap ada baiknya Anda perlu memahami kodenya sehingga Anda dapat menulis JSX sendiri dengan nyaman.

Berikut hasil jadinya:

JSX memungkinkan Anda menulis markup mirip HTML di dalam file JavaScript, sehingga membuat logika rendering dan konten berada pada satu tempat yang sama. Terkadang Anda akan ingin menambahkan sedikit logika JavaScript atau merujuk pada properti yang dinamis di dalam markup tersebut. Dalam situasi ini, Anda dapat menggunakan tanda kurung kurawal pada JSX untuk membuka akses ke JavaScript.

Mengoper string dengan tanda kutip

Ketika Anda ingin oper atribut string ke JSX, Anda memasukkannya ke dalam tanda kutip tunggal atau ganda. Perhatikan kode berikut.

export default function Avatar() {
  return (
    <img
      className="avatar"
      src="https://i.imgur.com/7vQD0fPs.jpg"
      alt="Gregorio Y. Zara"
    />
  );
}

Di sini kode tersebut, "https://i.imgur.com/7vQD0fPs.jpg" dan "Gregorio Y. Zara" sedang dioper sebagai string.

Namun bagaimana jika Anda ingin secara dinamis menentukan teks src atau alt ? Anda dapat menggunakan nilai dari JavaScript dengan mengganti kode seperti berikut:

export default function Avatar() {
  const avatar = 'https://i.imgur.com/7vQD0fPs.jpg';
  const description = 'Gregorio Y. Zara';
  return (
    <img
      className="avatar"
      src={avatar}
      alt={description}
    />
  );
}

Perhatikan perbedaan antara className="avatar", yang menentukan nama kelas CSS "avatar" yang membuat gambar bulat, dan src={avatar} yang membaca nilai variabel JavaScript disebut avatar. Hal itu terjadi karena kurung kurawal memungkinkan Anda bekerja dengan JavaScript langsung di markup Anda.

Menggunakan kurung kurawal: Jendela ke dunia JavaScript

JSX merupakan cara khusus dalam menulis JavaScript. Artinya, memungkinkan untuk menggunakan JavaScript di dalamnya - dengan kurung kurawal { }. Contohnya di bawah ini pertama perlu mendeklarasikan sebuah nama untuk ilmuwan, name, kemudian menyematkannya dengan kurung kurawal di dalam h1:

export default function TodoList() {
  const name = 'Gregorio Y. Zara';
  return (
    <h1>{name}'s To Do List</h1>
  );
}

Sekarang kita ubah nilai name dari 'Gregorio Y. Zara' menjadi 'Hedy Lamarr'. Lihat bagaimana judul daftar berubah?

Setiap ekspresi JavaScript akan berfungsi di antara kurung kurawal, termasuk fungsi seperti formatDate(), perhatikan kode berikut:

const today = new Date();

function formatDate(date) {
  return new Intl.DateTimeFormat(
    'en-US',
    { weekday: 'long' }
  ).format(date);
}

export default function TodoList() {
  return (
    <h1>To Do List for {formatDate(today)}</h1>
  );
}

Dimana dapat menggunakan kurung kurawal?

Anda hanya dapat menggunakan kurung kurawal (curly braces) dalam dua cara di dalam JSX:

  1. Sebagai teks langsung di dalam tag JSX: < h1 >Daftar Tugas {name} berfungsi, tetapi < {tag} >Daftar Tugas Gregorio Y. Zara tidak akan berhasil.
  2. Sebagai atribut yang mengikuti tanda dengan src={avatar} akan membaca variabel avatar, tetapi src="{avatar}" akan mengoper sebagai string "{avatar}".

Menggunakan "kurung kurawal ganda": CSS dan objek lain di JSX

Selain string, angka, dan ekspresi JavaScript lainnya, Anda bahkan dapat mengoper objek dalam JSX. Objek juga ditandai dengan kurung kurawal, seperti { name: "Hedy Lamarr", inventions: 5 }. Oleh karena itu, untuk mengoper objek JavaScript di JSX, Anda harus membungkus objek tersebut dalam sepasang kurung kurawal lainnya seperti ini: person={{ name: "Hedy Lamarr", inventions: 5 }}.

Anda mungkin melihat ini pada gaya CSS inline dalam JSX. React tidak mengharuskan Anda untuk menggunakan gaya inline (kelas CSS berfungsi lebih baik untuk kebanyakan kasus). Namun, ketika Anda membutuhkan gaya inline, Anda dapat mengoper objek ke atribut style seperti kode berikut:

export default function TodoList() {
  return (
    <ul style={{
      backgroundColor: 'black',
      color: 'pink'
    }}>
      <li>Improve the videophone</li>
      <li>Prepare aeronautics lectures</li>
      <li>Work on the alcohol-fuelled engine</li>
    </ul>
  );
}

Sekarang kita ubah nilai dari backgroundColor dan color.

Anda dapat melihat objek JavaScript di dalam kurung kurawal dengan jelas ketika Anda menulisnya seperti ini:

<ul style={
  {
    backgroundColor: 'black',
    color: 'pink'
  }
}>

Ketika Anda melihat {{ dan }} di dalam JSX, Anda akan tahu bahwa itu tidak lebih dari objek di dalam kurung kurawal JSX.

Anda dapat memasukkan beberapa ekspresi ke dalam satu objek, dan merujuk pada objek tersebut di dalam JSX menggunakan kurung kurawal. Sebagai contoh perhatikan kode berikut:

const person = {
  name: 'Gregorio Y. Zara',
  theme: {
    backgroundColor: 'black',
    color: 'pink'
  }
};

export default function TodoList() {
  return (
    <div style={person.theme}>
      <h1>{person.name}'s Todos</h1>
      <img
        className="avatar"
        src="https://i.imgur.com/7vQD0fPs.jpg"
        alt="Gregorio Y. Zara"
      />
      <ul>
        <li>Improve the videophone</li>
        <li>Prepare aeronautics lectures</li>
        <li>Work on the alcohol-fuelled engine</li>
      </ul>
    </div>
  );
}

Pada contoh kode tersebut, objek JavaScript person berisi sebuah string name dan sebuah objek theme:

const person = {
  name: 'Gregorio Y. Zara',
  theme: {
    backgroundColor: 'black',
    color: 'pink'
  }
};

Komponen dapat menggunakan nilai-nilai dari objek person seperti ini:

<div style={person.theme}>
  <h1>{person.name}'s Todos</h1>

JSX sangat sederhana sebagai bahasa templating karena memungkinkan Anda untuk mengorganisir data dan logika menggunakan JavaScript.

Selesaikan langkah-langkah praktikum berikut ini menggunakan editor Visual Studio Code (VS Code) atau code editor lain kesukaan Anda. Jawablah di laporan praktikum Anda pada setiap soal yang ada di beberapa langkah praktikum ini.

Langkah 1: Buat Komponen Baru

Buatlah file baru di src/components/todolist.tsx berisi kode seperti berikut:

const person = {
  name: 'Gregorio Y. Zara',
  theme: {
    backgroundColor: 'black',
    color: 'pink'
  }
};

export default function TodoList() {
  return (
    <div style={person.theme}>
      <h1>{person}'s Todos</h1>
      <img
        className="avatar"
        src="https://i.imgur.com/7vQD0fPs.jpg"
        alt="Gregorio Y. Zara"
      />
      <ul>
        <li>Improve the videophone</li>
        <li>Prepare aeronautics lectures</li>
        <li>Work on the alcohol-fuelled engine</li>
      </ul>
    </div>
  );
}

Langkah 2: Impor Komponen

Lakukan impor komponen di src/app/page.tsx seperti berikut ini.

import { Gallery } from "@/components/gallery";
import TodoList from "@/components/todolist";

export default function Home() {
  return (
    <section>
      <h1 className="font-semibold text-slate-900 truncate pr-20 text-center">Ilmuwan yang luar biasa</h1>
      <hr />
      <Gallery />
      <hr />
      <TodoList />
    </section>
  );
}

Langkah 3: Ubah ekspresi URL di src

Tetap di file src/components/todolist.tsx ubahlah objek person dan tambah variabel baseUrl seperti di bawah ini. URL lengkap gambar dibagi menjadi empat bagian: URL dasar, imageId, imageSize, dan ekstensi file.

Kita ingin URL gambar menggabungkan atribut-atribut ini bersama-sama: URL dasar (selalu 'https://i.imgur.com/'), imageId ('7vQD0fP'), imageSize ('s'), dan ekstensi file (selalu '.jpg'). Namun, ada yang salah dengan atribut src.

Bisakah anda memperbaikinya?

const baseUrl = 'https://i.imgur.com/';
const person = {
  name: 'Gregorio Y. Zara',
  imageId: '7vQD0fP',
  imageSize: 's',
  theme: {
    backgroundColor: 'black',
    color: 'pink'
  }
};

export default function TodoList() {
  return (
    <div style={person.theme}>
      <h1>{person.name}'s Todos</h1>
      <img
        className="avatar"
        src="{baseUrl}{person.imageId}{person.imageSize}.jpg"
        alt={person.name}
      />
      <ul>
        <li>Improve the videophone</li>
        <li>Prepare aeronautics lectures</li>
        <li>Work on the alcohol-fuelled engine</li>
      </ul>
    </div>
  );
}

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.

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 > seperti kode berikut:

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.

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 komponen Avatar beberapa props dalam dua langkah.

Langkah 1: Mengoper props ke komponen anak

Pertama-tama, kirimkan beberapa props pada komponen 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.

import { getImageUrl } from './utils';

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>
  );
}
export function getImageUrl(person, size = 's') {
  return (
    'https://i.imgur.com/' +
    person.imageId +
    size +
    '.jpg'
  );
}

Hasilnya:

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 dapat memecahnya menjadi props tersendiri.

Jangan melewatkan pasangan kurung kurawal { dan } di dalam tanda kurung ( dan ) saat menyatakan props sebagai parameter seperti kode ini:

function Avatar({ person, size }) {
  // ...
}

Sintaksis ini disebut "destructuring" dan ini berfungsi untuk membaca properti dari parameter fungsi, maka sebaiknya tulis seperti berikut ini:

function Avatar(props) {
  let person = props.person;
  let size = props.size;
  // ...
}

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 meletakkan = dan nilai bawaannya tepat setelah parameter seperti kode berikut ini:

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 props-nya secara langsung, ini akan masuk akal untuk menggunakan sintaksis "spread" yang mana lebih ringkas seperti kode berikut:

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 akan 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 browser:

<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';

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.

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.)

export default function Clock({ color, time }) {
  return (
    <h1 style={{ color: color }}>
      {time}
    </h1>
  );
}

Hasilnya:

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.

Selesaikan langkah-langkah praktikum berikut ini menggunakan editor Visual Studio Code (VS Code) atau code editor lain kesukaan Anda. Jawablah di laporan praktikum Anda pada setiap soal yang ada di beberapa langkah praktikum ini.

Langkah 1: Buat Komponen Baru

Buatlah file baru di src/components/mygallery.tsx berisi kode seperti berikut:

import { getImageUrl } from '@/utils/utils';

export default function MyGallery() {
  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>
  );
}

Langkah 2: Buat fungsi getImageUrl

Buatlah file baru di src/utils/utils.tsx berisi kode seperti berikut:

export function getImageUrl(imageId, size = 's') {
  return (
    'https://i.imgur.com/' +
    imageId +
    size +
    '.jpg'
  );
}

Langkah 3: Buat komponen baru

Buatlah file baru di src/components/myprofile.tsx berisi kode seperti berikut:

import { getImageUrlV2 } from '@/utils/utils';

function MyAvatar({ person, size }) {
  return (
    <img
      className="avatar"
      src={getImageUrl(person, 'b')}
      alt={person.name}
      width={size}
      height={size}
    />
  );
}

export default function MyProfile() {
  return (
    <MyAvatar
      size={40}
      person={{ 
        name: 'Gregorio Y. Zara', 
        imageId: '7vQD0fP'
      }}
    />
  );
}

Tambahkan fungsi getImageUrlV2 seperti berikut di file yang sama yaitu utils.tsx

src/utils/utils.tsx

export function getImageUrlV2(person, size) {
  return (
    'https://i.imgur.com/' +
    person.imageId +
    size +
    '.jpg'
  );
}

Pada contoh ini, komponen MyAvatar menerima prop size yang berupa angka dan akan digunakan untuk menentukan lebar dan tinggi < img >. Prop size dibuat 40 pada contoh ini. Bagaimanapun, jika Anda membuka gambar tersebut di web, Anda akan melihat bahwa gambarnya akan lebih besar (160 piksel). Ukuran gambar yang sebenarnya ditentukan oleh ukuran thumbnail yang Anda minta.

Langkah 4: Buat komponen baru MyProfileV2

Buatlah file baru di src/components/myprofilev2.tsx berisi kode seperti berikut:

export default function MyProfileV2() {
  return (
    <div>
      <div className="card">
        <div className="card-content">
          <h1>Foto</h1>
          <img
            className="avatar"
            src="https://i.imgur.com/OKS67lhm.jpg"
            alt="Aklilu Lemma"
            width={70}
            height={70}
          />
        </div>
      </div>
      <div className="card">
        <div className="card-content">
          <h1>Tentang</h1>
          <p>Aklilu Lemma adalah seorang ilmuwan terkemuka dari etiopia yang telah menemukan pengobatan alami untuk skistosomiasis.</p>
        </div>
      </div>
    </div>
  );
}

Selamat, Anda telah berhasil menyelesaikan codelab ini. Beberapa konsep ReactJS yang lain akan dipelajari pada pertemuan berikutnya.

Apa selanjutnya?

Silakan cek beberapa sumber belajar lainnya...

Referensi