Bab 2: Import & Export Komponen

2 menit baca

Kenapa Perlu Import/Export?

Bayangin kamu punya lemari baju dengan satu laci raksasa — semua baju, celana, kaos kaki, jaket dicampur jadi satu. Susah cari, kan?

Sekarang bayangin lemari dengan laci terpisah: laci kaos, laci celana, laci jaket. Mau ambil kaos? Langsung buka laci kaos.

Import/Export di React = sistem laci. Setiap component punya "laci" sendiri (file sendiri), dan kamu ambil (import) yang dibutuhkan.


Dua Jenis Export

1. Default Export (Satu per File)

jsx
// file: Tombol.jsx
export default function Tombol() {
  return <button>Klik</button>;
}

Import-nya:

jsx
import Tombol from './Tombol';        // ✅ Nama bebas!
import TombolKeren from './Tombol';   // ✅ Ini juga valid!
import Apapun from './Tombol';        // ✅ Nama terserah kamu!

Dengan default export, kamu bebas kasih nama apa aja saat import. React nggak peduli — yang penting path file-nya benar.

2. Named Export (Bisa Banyak per File)

jsx
// file: components.jsx
export function Tombol() {
  return <button>Klik</button>;
}

export function Input() {
  return <input type="text" />;
}

export function Badge() {
  return <span className="badge">New</span>;
}

Import-nya:

jsx
import { Tombol, Input, Badge } from './components';  // ✅ Harus pakai nama PERSIS
import { Tombol } from './components';                 // ✅ Ambil satu aja juga bisa
import { Input as InputTeks } from './components';     // ✅ Rename pakai "as"

Dengan named export, nama HARUS sama dengan yang di-export (kecuali pakai as untuk rename).


Kapan Pakai Default vs Named?

SituasiPakaiAlasan
Satu component utama per fileexport defaultKonvensi React — 1 file = 1 component utama
Banyak utility/helper di satu fileexport (named)Biar bisa import yang dibutuhkan aja
Component kecil yang terkaitexport (named)Grup component yang saling berhubungan

Konvensi Umum di Dunia React

src/ ├── components/ │ ├── Navbar.jsx ← export default Navbar │ ├── Footer.jsx ← export default Footer │ ├── KartuProduk.jsx ← export default KartuProduk │ └── ui/ │ ├── Tombol.jsx ← export default Tombol │ └── index.js ← re-export semua: export { Tombol } from './Tombol' ├── utils/ │ └── helpers.js ← export function formatRupiah() { ... } │ export function formatTanggal() { ... } └── App.jsx

Rule of thumb:

  • File component → export default
  • File utility/helper → named export

Contoh Lengkap: Struktur Project

File: src/components/Header.jsx

jsx
export default function Header({ judul }) {
  return (
    <header style={{ background: "#1a1a2e", color: "white", padding: "20px" }}>
      <h1>{judul}</h1>
    </header>
  );
}

File: src/components/KartuProduk.jsx

jsx
export default function KartuProduk({ nama, harga, gambar }) {
  return (
    <div style={{ border: "1px solid #ddd", borderRadius: "8px", padding: "16px", width: "200px" }}>
      <img src={gambar} alt={nama} style={{ width: "100%", borderRadius: "4px" }} />
      <h3>{nama}</h3>
      <p style={{ color: "#e94560", fontWeight: "bold" }}>
        Rp {harga.toLocaleString()}
      </p>
      <button style={{ width: "100%", padding: "8px", cursor: "pointer" }}>
        Beli
      </button>
    </div>
  );
}

File: src/components/Footer.jsx

jsx
export default function Footer() {
  return (
    <footer style={{ background: "#0f3460", color: "white", padding: "16px", textAlign: "center" }}>
      <p>© 2024 Toko Keren</p>
    </footer>
  );
}

File: src/utils/format.js

js
export function formatRupiah(angka) {
  return `Rp ${angka.toLocaleString("id-ID")}`;
}

export function formatTanggal(tanggal) {
  return new Date(tanggal).toLocaleDateString("id-ID", {
    day: "numeric",
    month: "long",
    year: "numeric",
  });
}

File: src/App.jsx

jsx
import Header from './components/Header';
import KartuProduk from './components/KartuProduk';
import Footer from './components/Footer';
import { formatRupiah } from './utils/format';

function App() {
  const produk = [
    { id: 1, nama: "Laptop", harga: 15000000, gambar: "/laptop.jpg" },
    { id: 2, nama: "Mouse", harga: 250000, gambar: "/mouse.jpg" },
    { id: 3, nama: "Keyboard", harga: 500000, gambar: "/keyboard.jpg" },
  ];

  return (
    <div>
      <Header judul="Toko Elektronik" />
      <main style={{ display: "flex", gap: "16px", padding: "20px", flexWrap: "wrap" }}>
        {produk.map((p) => (
          <KartuProduk key={p.id} nama={p.nama} harga={p.harga} gambar={p.gambar} />
        ))}
      </main>
      <Footer />
    </div>
  );
}

export default App;

Re-export (Barrel Export)

Kalau kamu punya banyak component di satu folder, bisa bikin file index.js untuk "kumpulkan" semua export:

File: src/components/ui/Tombol.jsx

jsx
export default function Tombol({ children, onClick }) {
  return <button onClick={onClick}>{children}</button>;
}

File: src/components/ui/Input.jsx

jsx
export default function Input({ placeholder, value, onChange }) {
  return <input placeholder={placeholder} value={value} onChange={onChange} />;
}

File: src/components/ui/index.js (barrel file)

js
export { default as Tombol } from './Tombol';
export { default as Input } from './Input';

Sekarang import jadi bersih:

jsx
// Tanpa barrel — harus import satu-satu
import Tombol from './components/ui/Tombol';
import Input from './components/ui/Input';

// Dengan barrel — satu baris!
import { Tombol, Input } from './components/ui';

Path Import

Relative Path (file lokal)

jsx
import Navbar from './Navbar';           // File di folder yang sama
import Footer from './components/Footer'; // File di subfolder
import Header from '../Header';          // File di folder parent
  • ./ = folder saat ini
  • ../ = naik satu level
  • ./components/ = masuk ke subfolder

Package Import (library dari npm)

jsx
import { useState } from 'react';           // Library React
import axios from 'axios';                   // Library HTTP
import { BrowserRouter } from 'react-router-dom';  // Library routing

Library dari npm nggak pakai ./ — cukup tulis nama package-nya.


⚠️ Jebakan

1. Campur Default dan Named Import

jsx
// File export:
export default function Utama() { ... }
export function Helper() { ... }

// Import BENAR:
import Utama, { Helper } from './file';  // Default + named dalam satu baris

// Import SALAH:
import { Utama, Helper } from './file';  // ❌ Utama bukan named export!

2. Lupa Extension di Beberapa Setup

jsx
// Vite biasanya nggak butuh extension:
import Navbar from './Navbar';      // ✅ Vite cari Navbar.jsx otomatis

// Tapi kalau error, coba tambahkan:
import Navbar from './Navbar.jsx';  // ✅ Eksplisit

3. Circular Import

jsx
// ❌ A import B, B import A — CIRCULAR!
// File A.jsx
import B from './B';
// File B.jsx
import A from './A';  // 💥 Bisa error atau undefined!

Solusi: Pindahkan shared logic ke file ketiga yang di-import keduanya.

4. Case Sensitivity

jsx
// File bernama: KartuProduk.jsx

import KartuProduk from './KartuProduk';   // ✅
import KartuProduk from './kartuproduk';   // ❌ Error di Linux/Mac!

🏋️ Challenge

Challenge 1: Pisahkan Component

Kamu punya kode ini dalam satu file. Pisahkan jadi 3 file terpisah, lalu import di App.jsx:

jsx
function Header() {
  return <h1>Blog Saya</h1>;
}

function Artikel({ judul, isi }) {
  return (
    <article>
      <h2>{judul}</h2>
      <p>{isi}</p>
    </article>
  );
}

function Footer() {
  return <p>© 2024</p>;
}

function App() {
  return (
    <div>
      <Header />
      <Artikel judul="Post 1" isi="Isi artikel pertama" />
      <Artikel judul="Post 2" isi="Isi artikel kedua" />
      <Footer />
    </div>
  );
}
✅ Solusi
jsx
// src/Header.jsx
export default function Header() {
  return <h1>Blog Saya</h1>;
}

// src/Artikel.jsx
export default function Artikel({ judul, isi }) {
  return (
    <article>
      <h2>{judul}</h2>
      <p>{isi}</p>
    </article>
  );
}

// src/Footer.jsx
export default function Footer() {
  return <p>© 2024</p>;
}

// src/App.jsx
import Header from './Header';
import Artikel from './Artikel';
import Footer from './Footer';

export default function App() {
  return (
    <div>
      <Header />
      <Artikel judul="Post 1" isi="Isi artikel pertama" />
      <Artikel judul="Post 2" isi="Isi artikel kedua" />
      <Footer />
    </div>
  );
}

Challenge 2: Barrel Export

Buat folder src/components/ui/ dengan 3 component (Tombol, Input, Badge). Buat barrel file index.js dan import semuanya dalam satu baris di App.

✅ Solusi
jsx
// src/components/ui/Tombol.jsx
export default function Tombol({ children }) {
  return <button style={{ padding: "8px 16px", cursor: "pointer" }}>{children}</button>;
}

// src/components/ui/Input.jsx
export default function Input({ placeholder }) {
  return <input placeholder={placeholder} style={{ padding: "8px", border: "1px solid #ccc" }} />;
}

// src/components/ui/Badge.jsx
export default function Badge({ teks }) {
  return <span style={{ background: "red", color: "white", padding: "2px 8px", borderRadius: "12px", fontSize: "12px" }}>{teks}</span>;
}

// src/components/ui/index.js
export { default as Tombol } from './Tombol';
export { default as Input } from './Input';
export { default as Badge } from './Badge';

// src/App.jsx
import { Tombol, Input, Badge } from './components/ui';

export default function App() {
  return (
    <div style={{ padding: "20px" }}>
      <h1>UI Components <Badge teks="3" /></h1>
      <Input placeholder="Ketik sesuatu..." />
      <Tombol>Submit</Tombol>
    </div>
  );
}

Sudah paham materi ini?

Tandai sebagai selesai untuk melacak progress-mu.