Bab 2: Import & Export Komponen
⏱ 2 menit bacaKenapa 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)
// file: Tombol.jsx
export default function Tombol() {
return <button>Klik</button>;
}Import-nya:
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)
// 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:
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?
| Situasi | Pakai | Alasan |
|---|---|---|
| Satu component utama per file | export default | Konvensi React — 1 file = 1 component utama |
| Banyak utility/helper di satu file | export (named) | Biar bisa import yang dibutuhkan aja |
| Component kecil yang terkait | export (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
export default function Header({ judul }) {
return (
<header style={{ background: "#1a1a2e", color: "white", padding: "20px" }}>
<h1>{judul}</h1>
</header>
);
}File: src/components/KartuProduk.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
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
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
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
export default function Tombol({ children, onClick }) {
return <button onClick={onClick}>{children}</button>;
}File: src/components/ui/Input.jsx
export default function Input({ placeholder, value, onChange }) {
return <input placeholder={placeholder} value={value} onChange={onChange} />;
}File: src/components/ui/index.js (barrel file)
export { default as Tombol } from './Tombol';
export { default as Input } from './Input';Sekarang import jadi bersih:
// 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)
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)
import { useState } from 'react'; // Library React
import axios from 'axios'; // Library HTTP
import { BrowserRouter } from 'react-router-dom'; // Library routingLibrary dari npm nggak pakai ./ — cukup tulis nama package-nya.
⚠️ Jebakan
1. Campur Default dan Named Import
// 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
// Vite biasanya nggak butuh extension:
import Navbar from './Navbar'; // ✅ Vite cari Navbar.jsx otomatis
// Tapi kalau error, coba tambahkan:
import Navbar from './Navbar.jsx'; // ✅ Eksplisit3. Circular Import
// ❌ 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
// 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:
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
// 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
// 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.