React dari Nol: Membangun Situs Web dengan 21 Contoh
React adalah pustaka JavaScript untuk membangun halaman web yang interaktif. Ia memecah halaman menjadi potongan-potongan kecil yang disebut komponen. Setiap komponen menerima data dan mengembalikan bagian dari halaman. Artikel ini membawa Anda dari menampilkan teks pertama sampai merakit situs web kecil dengan menu, kartu yang digerakkan data, dan footer. Setiap contoh adalah berkas sungguhan yang sudah dijalankan, dan keluaran yang ditampilkan adalah keluaran sebenarnya.
Yang Anda butuhkan
Anda memerlukan Node.js 18 atau yang lebih baru, pengetahuan dasar JavaScript, dan editor apa pun. Pasang paketnya dengan npm install [email protected] [email protected], lalu jalankan setiap contoh dengan penguji artikel ini. Contoh yang memiliki langkah mengklik tombol di browser tiruan yang dibuat dengan jsdom.
Ilustrasi
Contoh 1: Menampilkan teks pertama
Komponen adalah fungsi yang mengembalikan JSX. Contoh ini membuat judul dan mengubahnya menjadi HTML dengan renderToStaticMarkup.
import React from "react";
export function App() {
return <h1>Halo React</h1>;
}
Keluaran sebenarnya
<h1>Halo React</h1>
Contoh 2: Menampilkan daftar dengan map
Gunakan map untuk mengubah larik menjadi satu li untuk setiap item. Ketika data berubah, halaman mengikutinya tanpa mengedit HTML.
import React from "react";
const fruits = ["Durian", "Manggis", "Mangga"];
export function App() {
return (
<ul>
{fruits.map(f => <li key={f}>{f}</li>)}
</ul>
);
}
Keluaran sebenarnya
<ul><li>Durian</li><li>Manggis</li><li>Mangga</li></ul>
Contoh 3: Mengirim props ke komponen
Props adalah data yang diberikan komponen induk kepada anaknya. Komponen yang sama bisa dipakai ulang dengan data yang berbeda.
import React from "react";
function Greeting({ name, age }) {
return <p>Halo {name}, umur {age} tahun</p>;
}
export function App() {
return (
<div>
<Greeting name="Budi" age={20} />
<Greeting name="Siti" age={22} />
</div>
);
}
Keluaran sebenarnya
<div><p>Halo Budi, umur 20 tahun</p><p>Halo Siti, umur 22 tahun</p></div>
Contoh 4: Render bersyarat
Gunakan && dan operator ternary untuk memilih apa yang muncul di halaman.
import React from "react";
function Status({ online }) {
return (
<div>
{online ? <span>Online</span> : <span>Offline</span>}
{online && <em>Siap chat</em>}
</div>
);
}
export function App() {
return <Status online={true} />;
}
Keluaran sebenarnya
<div><span>Online</span><em>Siap chat</em></div>
Contoh 5: Fragment
Ketika Anda tidak menginginkan div tambahan, bungkus beberapa elemen dengan <> ... </>.
import React from "react";
function Header() {
return (
<>
<h2>Judul</h2>
<p>Tanpa pembungkus div</p>
</>
);
}
export function App() {
return <Header />;
}
Keluaran sebenarnya
<h2>Judul</h2><p>Tanpa pembungkus div</p>
Contoh 6: Key dalam tabel
Bangun tabel dari data dan gunakan id sebagai key agar React dapat melacak setiap baris.
import React from "react";
const students = [
{ id: 1, name: "Budi", score: 85 },
{ id: 2, name: "Siti", score: 72 },
];
export function App() {
return (
<table>
<tbody>
{students.map(s => (
<tr key={s.id}>
<td>{s.name}</td>
<td>{s.score}</td>
</tr>
))}
</tbody>
</table>
);
}
Keluaran sebenarnya
<table><tbody><tr><td>Budi</td><td>85</td></tr><tr><td>Siti</td><td>72</td></tr></tbody></table>
Contoh 7: Style sebagai objek
Style di React menerima objek dengan penulisan camelCase, seperti backgroundColor dan borderRadius.
import React from "react";
const box = {
padding: 12,
backgroundColor: "#eef4ff",
borderRadius: 8,
color: "#1a1a1a",
};
export function App() {
return <div style={box}>Kotak yang dihias dengan objek style</div>;
}
Keluaran sebenarnya
<div style="padding:12px;background-color:#eef4ff;border-radius:8px;color:#1a1a1a">Kotak yang dihias dengan objek style</div>
Contoh 8: children
Letakkan JSX di antara tag pembuka dan penutup sehingga komponen dapat membungkus konten apa pun.
import React from "react";
function Card({ title, children }) {
return (
<section>
<h3>{title}</h3>
<div>{children}</div>
</section>
);
}
export function App() {
return (
<Card title="Berita">
<p>Isi yang dikirim ke children</p>
</Card>
);
}
Keluaran sebenarnya
<section><h3>Berita</h3><div><p>Isi yang dikirim ke children</p></div></section>
Contoh 9: Penghitung dengan state
useState menyimpan nilai yang berubah. Memanggil setter membuat React merender ulang. Contoh ini mengklik tombol dua kali dan menampilkan perubahannya.
import React, { useState } from "react";
export function App() {
const [count, setCount] = useState(0);
return (
<div>
<p data-out>Hitung: {count}</p>
<button id="inc" onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
export const steps = ["#inc", "#inc"];
Keluaran sebenarnya
Teks awal: Hitung: 0
Setelah klik ke-1: Hitung: 1
Setelah klik ke-2: Hitung: 2
Contoh 10: Input terkendali
Nilai input dikendalikan oleh state dan diperbarui di onChange pada setiap ketukan tombol. Contoh ini menampilkan nilai awal nol karakter.
import React, { useState } from "react";
export function App() {
const [text, setText] = useState("");
return (
<div>
<input id="box" value={text} onChange={e => setText(e.target.value)} />
<p>Sudah diketik: {text.length} karakter</p>
</div>
);
}
Keluaran sebenarnya
<div><input id="box" value=""/><p>Sudah diketik: 0 karakter</p></div>
Contoh 11: Saklar hidup/mati
Simpan nilai boolean di state dan balikkan dengan !on setiap kali diklik.
import React, { useState } from "react";
export function App() {
const [on, setOn] = useState(false);
return (
<div>
<p data-out>{on ? "Menyala" : "Mati"}</p>
<button id="toggle" onClick={() => setOn(!on)}>Ganti</button>
</div>
);
}
export const steps = ["#toggle", "#toggle"];
Keluaran sebenarnya
Teks awal: Mati
Setelah klik ke-1: Menyala
Setelah klik ke-2: Mati
Contoh 12: useEffect
Efek berjalan setelah render. Gunakan untuk pekerjaan seperti memuat data atau menyiapkan sesuatu ketika komponen pertama kali muncul.
import React, { useEffect, useState } from "react";
export function App() {
const [message, setMessage] = useState("Memuat");
useEffect(() => {
setMessage("Selesai dimuat (dari useEffect)");
}, []);
return <p data-out>{message}</p>;
}
export const steps = [];
Keluaran sebenarnya
Teks awal: Selesai dimuat (dari useEffect)
Contoh 13: Formulir yang menyimpan nilainya
Baca isi input ke dalam state dan simpan ketika tombol diklik. Contoh ini dimulai dengan nama Budi.
import React, { useState } from "react";
export function App() {
const [name, setName] = useState("Budi");
const [saved, setSaved] = useState("");
return (
<div>
<input value={name} onChange={e => setName(e.target.value)} />
<button id="save" onClick={() => setSaved(name)}>Simpan</button>
<p data-out>Tersimpan: {saved || "Belum ada"}</p>
</div>
);
}
export const steps = ["#save"];
Keluaran sebenarnya
Teks awal: Tersimpan: Belum ada
Setelah klik ke-1: Tersimpan: Budi
Contoh 14: Daftar tugas
Tambahkan item dengan membuat larik baru memakai spread, bukan mengubah larik lama.
import React, { useState } from "react";
let nextId = 1;
export function App() {
const [items, setItems] = useState([]);
const add = () => {
const id = nextId++;
setItems([...items, { id, text: "Tugas ke-" + id }]);
};
return (
<div>
<button id="add" onClick={add}>Tambah tugas</button>
<ul data-out>{items.map(i => <li key={i.id}>{i.text}</li>)}</ul>
</div>
);
}
export const steps = ["#add", "#add"];
Keluaran sebenarnya
Teks awal:
Setelah klik ke-1: Tugas ke-1
Setelah klik ke-2: Tugas ke-1Tugas ke-2
Contoh 15: Context
Teruskan nilai tema ke komponen yang jauh di dalam tanpa mengirim props melalui setiap tingkat.
import React, { createContext, useContext } from "react";
const ThemeContext = createContext("light");
function Button() {
const theme = useContext(ThemeContext);
return <button>Tema: {theme}</button>;
}
export function App() {
return (
<ThemeContext.Provider value="dark">
<Button />
</ThemeContext.Provider>
);
}
Keluaran sebenarnya
<button>Tema: dark</button>
Contoh 16: useReducer
Kelola state yang punya beberapa nilai atau aksi dengan menggunakan action dan reducer.
import React, { useReducer } from "react";
function reducer(state, action) {
switch (action.type) {
case "inc": return { count: state.count + 1 };
case "dec": return { count: state.count - 1 };
default: return state;
}
}
export function App() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div>
<p data-out>Nilai: {state.count}</p>
<button id="inc" onClick={() => dispatch({ type: "inc" })}>+</button>
<button id="dec" onClick={() => dispatch({ type: "dec" })}>-</button>
</div>
);
}
export const steps = ["#inc", "#inc", "#dec"];
Keluaran sebenarnya
Teks awal: Nilai: 0
Setelah klik ke-1: Nilai: 1
Setelah klik ke-2: Nilai: 2
Setelah klik ke-3: Nilai: 1
Contoh 17: Hook buatan sendiri
Letakkan logika state dalam fungsi yang namanya diawali use sehingga Anda dapat memakainya kembali.
import React, { useState } from "react";
function useCounter(start) {
const [count, setCount] = useState(start);
return { count, increment: () => setCount(c => c + 1) };
}
export function App() {
const { count, increment } = useCounter(10);
return (
<div>
<p data-out>Nilai sekarang: {count}</p>
<button id="inc" onClick={increment}>Tambah</button>
</div>
);
}
export const steps = ["#inc"];
Keluaran sebenarnya
Teks awal: Nilai sekarang: 10
Setelah klik ke-1: Nilai sekarang: 11
Contoh 18: useMemo
Simpan hasil perhitungan yang berat dan hitung ulang hanya ketika dependensinya berubah.
import React, { useMemo } from "react";
const numbers = [1, 2, 3, 4, 5];
export function App() {
const total = useMemo(() => numbers.reduce((a, b) => a + b, 0), []);
return <p>Jumlah = {total}</p>;
}
Keluaran sebenarnya
<p>Jumlah = 15</p>
Contoh 19: Tab
Pilih konten dari objek sesuai tab yang diklik pengguna. Contoh ini berpindah antara tab A dan tab B.
import React, { useState } from "react";
const content = {
a: "Isi tab A",
b: "Isi tab B",
};
export function App() {
const [tab, setTab] = useState("a");
return (
<div>
<button id="tab-a" onClick={() => setTab("a")}>Tab A</button>
<button id="tab-b" onClick={() => setTab("b")}>Tab B</button>
<p data-out>{content[tab]}</p>
</div>
);
}
export const steps = ["#tab-b", "#tab-a"];
Keluaran sebenarnya
Teks awal: Isi tab A
Setelah klik ke-1: Isi tab B
Setelah klik ke-2: Isi tab A
Contoh 20: Memuat data
Muat data ketika komponen pertama kali muncul, tampilkan pesan memuat, lalu tampilkan daftarnya ketika pemuatan selesai.
import React, { useEffect, useState } from "react";
const DATA = ["Budi", "Siti", "Dedi"];
export function App() {
const [loading, setLoading] = useState(true);
const [items, setItems] = useState([]);
const load = () => {
setLoading(true);
setTimeout(() => { setItems(DATA); setLoading(false); }, 0);
};
useEffect(() => { load(); }, []);
return (
<div>
<button id="reload" onClick={load}>Muat ulang</button>
<div data-out>{loading ? <p>Memuat...</p> : <ul>{items.map(n => <li key={n}>{n}</li>)}</ul>}</div>
</div>
);
}
export const steps = ["#reload"];
Keluaran sebenarnya
Teks awal: Memuat...
Setelah klik ke-1: BudiSitiDedi
Contoh 21: Situs kecil dari komponen
Gabungkan semuanya menjadi satu halaman dengan header dan menu, bagian hero, kartu layanan yang dibuat dari data, dan footer.
import React from "react";
const menu = ["Beranda", "Layanan", "Kontak"];
const services = [
{ id: 1, name: "Situs web perusahaan", price: 15000 },
{ id: 2, name: "Toko online", price: 25000 },
];
function Header() {
return (
<header style={{ background: "#1a2b4c", color: "#fff", padding: "12px" }}>
<strong>PT Contoh</strong>
<nav>{menu.map(m => <a key={m} href="#" style={{ marginLeft: 12, color: "#fff" }}>{m}</a>)}</nav>
</header>
);
}
function Hero({ title, subtitle }) {
return (
<section>
<h1>{title}</h1>
<p>{subtitle}</p>
</section>
);
}
function ServiceCard({ name, price }) {
return (
<div style={{ border: "1px solid #ccc", borderRadius: 8, padding: 12, margin: 8 }}>
<h3>{name}</h3>
<p>Harga mulai Rp {price.toLocaleString("en-US")}</p>
</div>
);
}
function Footer() {
return <footer><small>© 2026 PT Contoh</small></footer>;
}
export function App() {
return (
<div>
<Header />
<main>
<Hero title="Selamat datang" subtitle="Kami membuat situs web untuk bisnis Anda" />
<div>{services.map(s => <ServiceCard key={s.id} name={s.name} price={s.price} />)}</div>
</main>
<Footer />
</div>
);
}
Keluaran sebenarnya
<div><header style="background:#1a2b4c;color:#fff;padding:12px"><strong>PT Contoh</strong><nav><a href="#" style="margin-left:12px;color:#fff">Beranda</a><a href="#" style="margin-left:12px;color:#fff">Layanan</a><a href="#" style="margin-left:12px;color:#fff">Kontak</a></nav></header><main><section><h1>Selamat datang</h1><p>Kami membuat situs web untuk bisnis Anda</p></section><div><div style="border:1px solid #ccc;border-radius:8px;padding:12px;margin:8px"><h3>Situs web perusahaan</h3><p>Harga mulai Rp 15,000</p></div><div style="border:1px solid #ccc;border-radius:8px;padding:12px;margin:8px"><h3>Toko online</h3><p>Harga mulai Rp 25,000</p></div></div></main><footer><small>© 2026 PT Contoh</small></footer></div>
Langkah berikutnya
Berikutnya, gunakan React Router untuk membagi situs menjadi beberapa halaman, panggil API sungguhan dengan fetch, dan gunakan Vite atau Next.js untuk membuat proyek. Setelah Anda memahami state dan props, menambah fitur hanya soal menyusun lebih banyak komponen.
Ringkasan
React membangun halaman dari komponen yang menerima props dan menyimpan state. Ketika state berubah, React merender ulang bagian yang terpengaruh. Ke-21 contoh ini mencakup semuanya, dari merender teks sampai merakit situs kecil yang lengkap, dan setiap keluaran dalam artikel ini berasal dari proses yang benar-benar dijalankan.