React dari Nol: Membangun Situs Web dengan 21 Contoh

React dari Nol: Membuat Website 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

Cara kerja React: data dan state masuk ke dalam komponen, yang menghasilkan HTML
Cara kerja React: data dan state masuk ke dalam komponen, yang menghasilkan HTML

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
Siklus state: klik memanggil setter, lalu React merender ulang
Siklus state: klik memanggil setter, lalu React merender ulang

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.