Dulu, ada momen pas kita mau update framework atau library favorit di proyek. Perasaan campur aduk itu pasti muncul: ada sedikit rasa excited karena bakal ada fitur baru yang bikin ngiler, tapi nggak bisa dipungkiri, ada juga deg-degannya. "Duh, apa aja nih yang berubah? Kode lama yang udah susah payah dibangun bakal pecah nggak ya?" Pertanyaan-pertanyaan itu sering banget melintas di pikiran. Kita langsung kepikiran, "Jangan-jangan bakal begadang lagi nih buat benerin bug yang muncul setelah update."
Pengalaman ini mungkin bukan cuma kita aja yang ngerasain. Hampir semua developer pernah mengalami sensasi kayak gini, apalagi kalau update-nya itu lumayan gede. Rasanya kayak mau nyobain mobil balap baru, tapi belum tahu pedal gasnya sensitif seberapa, atau remnya pakem banget apa enggak. Nah, perasaan campur aduk inilah yang mungkin lagi dirasakan para developer React dan Next.js saat mendengar kabar React 19 dan integrasinya yang bakal datang dengan Next.js 15. Tapi tenang, kali ini ceritanya justru lebih seru, lebih menjanjikan, dan bikin kita nggak sabar buat nyobain! Kali ini kita nggak perlu terlalu deg-degan, karena update ini justru banyak membawa kabar baik, apalagi buat performa dan kemudahan ngoding.
π§ Apa Itu React 19 & Kenapa Beda?
Kalau kamu udah lama ngoding pakai React, kamu pasti familiar dengan hal-hal ini:
- Harus bikin
useState,useEffect, danfetchtiap kali kirim data form - Bikin tombol loading sendiri, handle error sendiri
- Dan yang paling sering... nulis API handler bolak-balik cuma buat validasi form sederhana π΅
Nah, React 19 hadir buat mengubah semua itu.
π React 19 bukan update biasa
React 19 itu bukan sekadar ganti versi. Ini transformasi besar yang bikin cara kita ngoding lebih simpel dan efisien.
Bayangin kamu biasa naik motor bebek buat antar orderan, sekarang dikasih motor listrik β tetap cepat, tapi lebih hemat tenaga dan nggak berisik.
π Apa yang Baru di React 19?
1. action(): Kirim Data Tanpa Ribet
Sekarang kamu bisa kirim data ke server langsung dari komponen React tanpa harus bikin API handler terpisah.
Misalnya kamu bikin form booking mobil? Tinggal definisikan fungsi server di action() dan panggil langsung dari <form>.
<form action={pesanMobil}>...</form>
Di balik layar, React & Next.js yang urus submit data β validasi β simpan ke DB.
Dulu:
β‘οΈ useState β handleSubmit β fetch β handle loading β handle error
Sekarang:
β‘οΈ action() β Done. β¨
2. Form API Baru: useFormStatus() & useFormState()
useFormStatus(): Cek apakah form sedang submitting, ada error, atau suksesuseFormState(): Ambil dan tangani state form yang berasal dari server (bukan dari client)
Dengan ini, kamu bisa bikin form:
- Ada loading state otomatis
- Error dari server langsung ditampilkan ke UI
- Tanpa harus bikin 3-4 state manual di komponen
3. useOptimistic(): UI Langsung Update Sebelum Server Balas
Salah satu fitur paling kerasa di React 19: Optimistic UI.
Misal: kamu klik tombol "Pesan Sekarang" β total booking langsung bertambah, meskipun server belum sempat kasih respon.
Baru nanti, kalau server bales error, UI bisa revert.
const [jumlah, setJumlah] = useOptimistic(10)
Kenapa ini penting?
- User merasa aplikasi cepat
- Responsif kayak native app
- Nggak perlu loading spinner di setiap klik
π§ͺ Perubahan Lain yang Ikut Diperbarui
- React Compiler (masih eksperimental): Compiler otomatis optimasi kode, mirip Svelte atau Solid
- Event Handling lebih ringan
- Transisi UI lebih smooth (via
startTransition)
βοΈ Perbandingan: Dulu vs Sekarang
Dulu (React <18):
- Form harus pakai
fetch,useState, danhandleSubmitmanual - Harus bikin loading dan error handler sendiri
- UI harus nunggu respon server dulu baru berubah
- Banyak boilerplate dan kode berulang
Sekarang (React 19 + Next.js 15):
- Form cukup pakai
action()+ Form API langsung di komponen - Loading & error otomatis ditangani via
useFormStatus() - UI bisa langsung berubah pakai
useOptimistic(), tanpa nunggu server - Kode jadi lebih pendek, lebih bersih, dan mudah dibaca
π§ Kenapa Ini Relevan?
Karena sekarang user udah terbiasa sama UX cepat (kayak Gojek, Tokopedia, Traveloka).
Kalau web kamu lemot dikit, user bisa langsung cabut.
React 19 bantu kamu ngejar UX modern, tapi tanpa harus jadi ahli JavaScript yang rumit.
Kita udah tahu fitur-fiturnya, tapi... gimana cara pakainya dalam proyek nyata?
Yuk lanjut ke studi kasus: web sewa mobil π
π Daftar Fitur Baru (Singkat, Tapi Nendang)
React 19 hadir dengan fitur-fitur baru yang tujuannya satu: bikin hidup developer lebih simpel dan UX lebih cepat. Berikut daftarnya dalam bentuk list + analogi + contoh kode π
1. β
action(): Jalankan Fungsi Server Langsung dari Form
Fungsi:
Memungkinkan kamu menjalankan fungsi server (seperti insert ke database) langsung dari form, tanpa bikin API route manual.
Analogi:
Kayak kamu pesan makanan di resto, dan pesananmu langsung masuk ke dapur β nggak perlu lewat admin, antrian, dll.
Contoh Kode:
// app/pesan/page.tsx
import { action } from 'react'
import { redirect } from 'next/navigation'
const pesanMobil = action(async (formData) => {
const nama = formData.get('nama') as string
const tanggal = formData.get('tanggal') as string
// Simpan data ke DB (pura-pura dulu)
await saveToDB(nama, tanggal)
redirect('/terima-kasih')
})
export default function Page() {
return (
<form action={pesanMobil}>
<input name="nama" placeholder="Nama Penyewa" required />
<input name="tanggal" type="date" required />
<button>Pesan Sekarang</button>
</form>
)
}
2. π§ useFormStatus(): Lacak Status Form Secara Otomatis
Fungsi:
Melacak status form saat dikirim, misalnya:
- Apakah sedang submit (
pending) - Apakah ada error
Analogi:
Seperti notifikasi driver Grab: βSedang dijemputβ, βSedang dalam perjalananβ, atau βSudah sampaiβ.
Contoh Kode:
'use client'
import { useFormStatus } from 'react-dom'
export function PesanButton() {
const { pending } = useFormStatus()
return (
<button type="submit" disabled={pending}>
{pending ? 'Memesan...' : 'Pesan Sekarang'}
</button>
)
}
3. π¦ useFormState(): Validasi Server Langsung ke UI
Fungsi:
Form bisa kirim dan menerima feedback langsung dari server. Cocok buat validasi nama, tanggal, dsb.
Nggak perlu bikin useState, useEffect, dan error handler manual lagi.
Analogi:
Kamu isi tanggal sewa β server langsung bilang salah atau bener, tanpa harus reload halaman atau fetch manual.
Contoh Kode:
'use client'
import { useFormState } from 'react-dom'
async function prosesForm(_prevState: any, formData: FormData) {
const nama = formData.get('nama')?.toString()
if (!nama || nama.length < 3) {
return { error: 'Nama minimal 3 huruf ya!' }
}
return { success: true }
}
export default function FormBooking() {
const [state, formAction] = useFormState(prosesForm, null)
return (
<form action={formAction}>
<input name="nama" placeholder="Nama Penyewa" />
{state?.error && <p className="text-red-500">{state.error}</p>}
<button>Pesan Mobil</button>
</form>
)
}
4. β‘ useOptimistic(): Optimistic UI Tanpa Ribet
Fungsi:
Bikin UI langsung update sebelum server bales. Kalau nanti server error, tinggal dibalik lagi.
Analogi:
Klik tombol β UI langsung berubah β server nyusul.
Kayak kamu klik βlikeβ di Instagram, dan ikon langsung berubah, walau sinyal lagi lemot.
Contoh Kode:
'use client'
import { useOptimistic, useTransition } from 'react'
export function JumlahBooking() {
const [jumlah, setJumlah] = useOptimistic(10)
const [isPending, startTransition] = useTransition()
function tambahBooking() {
startTransition(() => {
setJumlah((prev) => prev + 1)
fetch('/api/tambah-booking', { method: 'POST' })
})
}
return (
<div>
<p>Total Booking: {jumlah}</p>
<button onClick={tambahBooking} disabled={isPending}>
{isPending ? 'Loading...' : 'Booking Lagi'}
</button>
</div>
)
}
5. π Transisi UI Lebih Smooth dengan startTransition()
Fungsi:
Membuat transisi UI berat (seperti filter, pencarian, sorting) jadi halus dan nggak nge-freeze.
Kamu bisa pisahkan mana update penting dan mana yang bisa ditunda sedikit.
Analogi:
Pas kamu ketik filter mobil, UI tetap responsif walau datanya belum semua dimuat β kayak Netflix saat kamu cari film.
Contoh Kode:
'use client'
import { startTransition, useState } from 'react'
export default function FilterMobil() {
const [filter, setFilter] = useState('')
function handleFilter(e: React.ChangeEvent<HTMLInputElement>) {
const value = e.target.value
startTransition(() => {
setFilter(value)
})
}
return (
<>
<input onChange={handleFilter} placeholder="Cari tipe mobil..." />
<p>Menampilkan hasil untuk: {filter}</p>
</>
)
}
Masing-masing fitur ini nggak cuma bikin kode lebih bersih, tapi juga membuat web terasa lebih cepat dan responsif untuk pengguna.
Next, yuk kita bahas gimana semua ini bisa diterapkan dalam proyek nyata: web sewa mobil π.
π 4. Studi Kasus: Web Sewa Mobil ala Tokocar
Bayangin kamu lagi bikin Tokocar β sebuah platform sewa mobil online. Fitur utamanya tentu aja:
- Booking mobil
- Tampilkan jumlah booking
- Validasi input penyewa
Dengan React 19 + Next.js 15, semua ini bisa dibuat dengan lebih simpel, bersih, dan cepat.
π Contoh: Booking Mobil dengan Server Action
Dulu, untuk submit form booking kamu harus:
- Setup
useState - Buat
handleSubmit - Panggil API dengan
fetch - Bikin endpoint API di
/api/booking
Sekarang? Cukup pakai Server Action dari React 19.
β Kode Lengkap
Halaman pesan:
// app/pesan/page.tsx
import { redirect } from "next/navigation";
import { SubmitButton } from "./SubmitButton";
export async function bookingMobil(formData: FormData) {
"use server";
const nama = formData.get("nama")?.toString();
const tanggal = formData.get("tanggal")?.toString();
if (!nama || !tanggal) {
throw new Error("Data tidak lengkap");
}
// Simulasi simpan ke DB
console.log("Booking disimpan:", { nama, tanggal });
redirect("/terima-kasih");
}
export default function Page() {
return (
<div className="flex flex-col gap-10 items-center justify-center min-h-screen">
<h2 className="text-2xl font-bold">Form Pesan</h2>
<form action={bookingMobil} className="flex flex-col gap-6">
<input name="nama" placeholder="Nama" required />
<input name="tanggal" type="date" required />
<SubmitButton />
</form>
</div>
);
}
Komponen tombol submit:
// app/pesan/SubmitButton.tsx
"use client";
import { useFormStatus } from "react-dom";
export function SubmitButton() {
const { pending } = useFormStatus();
return (
<button
type="submit"
disabled={pending}
className="px-4 py-2 bg-blue-600 text-white rounded disabled:opacity-50"
>
{pending ? "Memesan..." : "Pesan Sekarang"}
</button>
);
}
Halaman terima kasih:
// app/terima-kasih/page.tsx
export default function Page() {
return (
<div className="flex flex-col items-center justify-center min-h-screen">
<h2 className="text-2xl font-bold">Terima kasih sudah memesan</h2>
</div>
);
}
Hasilnyaa:

π Catatan Tambahan
Agar ini bekerja:
- Proyek kamu wajib pakai App Router (
/app/, bukan/pages/) - File harus berada di direktori
app/dan di-render di server - Pastikan Next.js >=15 dan React >=19
π¨ Contoh: Optimistic UI dengan useOptimistic()
Tampilkan jumlah total booking yang langsung naik ketika user klik tombol, tanpa harus nunggu server bales.
β Kode Lengkap
Komponen useOptimistic:
"use client";
import { useOptimistic, useTransition, useState } from "react";
export function TotalBooking() {
const [serverJumlah, setServerJumlah] = useState<number>(20); // nilai awal dari DB
const [optimisticJumlah, setOptimisticJumlah] = useOptimistic(serverJumlah);
const [isPending, startTransition] = useTransition();
const tambahBooking = () => {
startTransition(() => {
setOptimisticJumlah((prev) => prev + 1);
fetch("/api/tambah-booking", { method: "POST" }) // dummy
.then(() => setServerJumlah((prev) => prev + 1));
});
};
return (
<div className="mb-4 space-y-2">
<p className="text-lg">Total Booking: {optimisticJumlah}</p>
<button
onClick={tambahBooking}
disabled={isPending}
className="px-4 py-2 bg-green-600 text-white rounded disabled:opacity-50"
>
{isPending ? "Memproses..." : "Booking Lagi"}
</button>
</div>
);
}
Hasilnya:

π Catatan Singkat:
useOptimistic(value)sekarang hanya butuh 1 argumen: nilai awalsetOptimisticValue((prev) => ...)digunakan untuk perubahan lokal- Setelah server update sukses, kamu wajib update state asli (
setJumlahServer) agar sinkron
π Contoh: Validasi Nama Penyewa dengan useActionState()
Validasi input langsung dari server tanpa harus bikin state dan handler manual di client.
β Kode Lengkap
"use client";
import { pesanMobil } from "./action";
import { SubmitButton } from "./SubmitButton";
import { useActionState } from "react";
const Form = () => {
const [state, formAction] = useActionState(pesanMobil, null);
return (
<form action={formAction} className="space-y-4">
<input
name="nama"
placeholder="Nama Penyewa"
className="border p-2 w-full"
/>
<input name="tanggal" type="date" className="border p-2 w-full" />
{state?.error && <p className="text-red-500">{state.error}</p>}
<SubmitButton />
</form>
);
};
export default Form;
π§ Singkatnya...
React 19 + Next.js 15 bantu kamu bikin:
β Form booking yang cepat & aman
β Feedback UI yang langsung terasa
β Validasi input tanpa ribet
β Kode yang ringkas dan gampang dirawat
Semua fitur tadi pas banget buat proyek web sewa mobil, atau jenis aplikasi lain yang interaktif dan berbasis form.
Ini kode lengkapnya:
Halaman pesan:
// app/pesan/page.tsx
import Form from "./Form";
import { TotalBooking } from "./TotalBooking";
export default function PesanPage() {
return (
<div className="p-8 max-w-xl mx-auto space-y-6">
<h1 className="text-2xl font-bold">Pesan Mobil</h1>
<Form />
<TotalBooking />
</div>
);
}
Komponen form:
// app/pesan/Form.tsx
"use client";
import { pesanMobil } from "./action";
import { SubmitButton } from "./SubmitButton";
import { useActionState } from "react";
const Form = () => {
const [state, formAction] = useActionState(pesanMobil, null);
return (
<form action={formAction} className="space-y-4">
<input
name="nama"
placeholder="Nama Penyewa"
className="border p-2 w-full"
/>
<input name="tanggal" type="date" className="border p-2 w-full" />
{state?.error && <p className="text-red-500">{state.error}</p>}
<SubmitButton />
</form>
);
};
export default Form;
Server action:
// app/pesan/action.ts
"use server";
import { redirect } from "next/navigation";
export type State = { error?: string; success?: boolean };
export async function pesanMobil(
_: State | null,
formData: FormData
): Promise<State> {
const nama = formData.get("nama")?.toString() || "";
const tanggal = formData.get("tanggal")?.toString() || "";
if (nama.length < 3) {
return { error: "Nama minimal 3 huruf." };
}
if (!tanggal) {
return { error: "Tanggal wajib diisi." };
}
// Simulasi simpan ke DB
console.log("βοΈ Booking disimpan:", { nama, tanggal });
redirect("/terima-kasih");
}
Komponen tombol submit:
// app/pesan/SubmitButton.tsx
"use client";
import { useFormStatus } from "react-dom";
export function SubmitButton() {
const { pending } = useFormStatus();
return (
<button
type="submit"
disabled={pending}
className="px-4 py-2 bg-blue-600 text-white rounded disabled:opacity-50"
>
{pending ? "Memesan..." : "Pesan Sekarang"}
</button>
);
}
Komponen useOptimistic:
// app/pesan/TotalBooking.tsx
"use client";
import { useOptimistic, useTransition, useState } from "react";
export function TotalBooking() {
const [serverJumlah, setServerJumlah] = useState<number>(20); // nilai awal dari DB
const [optimisticJumlah, setOptimisticJumlah] = useOptimistic(serverJumlah);
const [isPending, startTransition] = useTransition();
const tambahBooking = () => {
startTransition(() => {
setOptimisticJumlah((prev) => prev + 1);
fetch("/api/tambah-booking", { method: "POST" }) // dummy
.then(() => setServerJumlah((prev) => prev + 1));
});
};
return (
<div className="mb-4 space-y-2">
<p className="text-lg">Total Booking: {optimisticJumlah}</p>
<button
onClick={tambahBooking}
disabled={isPending}
className="px-4 py-2 bg-green-600 text-white rounded disabled:opacity-50"
>
{isPending ? "Memproses..." : "Booking Lagi"}
</button>
</div>
);
}
API tambah booking:
// app/api/tambah-booking/route.ts
import { NextResponse } from "next/server";
export async function POST() {
console.log("β
Booking ditambahkan (dummy)");
return NextResponse.json({ ok: true });
}
Hasilnya:

π€ 5. Kapan Harus Dipakai?
βBagus sih... Tapi kapan cocoknya dipakai?β
Nah, React 19 di Next.js 15 bukan solusi buat semua jenis proyek. Tapi dia sangat cocok buat kebutuhan yang serba interaktif, responsif, dan efisien.
Kalau proyekmu punya ciri-ciri di bawah ini, kamu wajib pertimbangkan:
β Cocok Dipakai Kalau...
- π Banyak Form & Booking
- Misalnya: form pemesanan mobil, motor, tiket, produk, dll.
- React 19 bikin alur submit data jauh lebih ringan, tanpa perlu bolak-balik bikin API route.
- Dengan
action()atau server action, kamu tinggalform action={handler}dan jalan.
- β‘ Ingin UI Cepat Tanpa JavaScript Berat
- React 19 memungkinkan kamu pakai Optimistic UI langsung dari server-side.
- Hasilnya: UX tetap mulus, tanpa overuse JS di client.
- π§Ή Pengen Ngurangin API Handler Manual
- Gak perlu lagi bikin
POST /api/simpan,PATCH /api/edit, dsb untuk form sederhana. - Semua bisa langsung dari form + server action.
- Gak perlu lagi bikin
- π SEO dan UX Harus Optimal
- Karena semua tetap jalan di server (Next.js 15), page tetap SSR/SSG friendly.
- UX meningkat, tanpa mengorbankan SEO.
π΅ Contoh Proyek yang Pas Pakai React 19
Kalau kamu bikin proyek seperti:
- Sewa mobil online (contoh: Tokocar)
- Sewa motor harian
- Booking tiket konser / event
- E-commerce ringan (produk terbatas, checkout cepat)
- Undangan digital dengan form RSVP
- Aplikasi survey / polling
Maka React 19 + Next.js 15 ini cocok banget. Kamu bisa dapetin:
- β¨ UX sekelas native app
- π§Ό Kode lebih bersih & maintainable
- π Logika tetap di server, lebih aman
π€· Kapan Belum Perlu?
Kalau kamu bikin:
- Landing page statis tanpa interaksi
- Blog sederhana hanya butuh Markdown
- Aplikasi super berat di sisi client (like drag & drop canvas editor)
...React 19 tetap bisa dipakai, tapi nggak terlalu ngasih dampak besar dibanding benefit-nya di proyek interaktif.
Intinya:
Kalau aplikasi kamu βklik β loading β kirim dataβ, React 19 adalah upgrade yang pantas banget dicoba.
π§Ό 6. Bonus: Hidup Lebih Simpel dengan React 19
React 19 ngajarin kita satu hal penting:
βJangan ribet kalau bisa simpel.β
Dulu, bikin form itu kayak bikin soto dari nol:
- Harus
useStatebuat tiap input useEffectbuat syncinghandleSubmit()manual- Panggil
fetch() - Bikin API handler lagi di
/api/...
Capek? Jelas π
Tapi sekarang?
Dengan React 19 + Next.js 15 kamu cukup:
<form action={handleBooking}>
<input name="nama" />
<button>Pesan</button>
</form>
Dan di handleBooking, kamu tulis aja:
'use server'
export async function handleBooking(formData: FormData) {
// Akses & simpan data langsung
}
Thatβs it.
π¦ Semua logic tetap di server
π Aman
β‘ Simpel
π‘ Gampang dibaca & dirawat
Penutup
Sebagai penutup, adopsi React 19 di Next.js 15 adalah lebih dari sekadar pembaruan versi; ini adalah gerbang menuju potensi baru yang signifikan untuk aplikasi web Anda. Setiap rilis baru dari React dan Next.js membawa kita lebih dekat pada pengembangan yang lebih efisien dan aplikasi yang lebih responsif, dan kombinasi versi terbaru ini tidak terkecuali.
Peningkatan kinerja yang dijanjikan, terutama dengan inovasi seperti React Forget dan penyempurnaan pada Server Components, berarti aplikasi Anda tidak hanya akan terasa lebih cepat bagi pengguna, tetapi juga akan lebih mudah diskalakan seiring pertumbuhan kebutuhan. Pengembangan yang lebih intuitif dan pengalaman developer yang lebih baik juga akan membebaskan Anda untuk fokus pada fitur inti dan inovasi, mengurangi boilerplate dan kompleksitas yang tidak perlu.
Mempertimbangkan migrasi ke kombinasi teknologi terkini ini adalah langkah strategis, terutama jika Anda sedang membangun aplikasi baru atau ingin merevitalisasi proyek yang sudah ada. Ini adalah kesempatan untuk tidak hanya mengikuti tren, tetapi untuk benar-benar berada di garis depan inovasi web, memanfaatkan tool yang dirancang untuk performa dan produktivitas maksimal.
Jadi, apakah Anda siap untuk membawa proyek Anda ke level berikutnya dengan memanfaatkan kekuatan penuh dari React 19 dan Next.js 15? Mulailah eksplorasi, pahami nuansanya, dan rasakan sendiri bagaimana perpaduan teknologi ini dapat mengubah cara Anda membangun web, membuka jalan bagi aplikasi yang lebih cepat, lebih efisien, dan lebih menyenangkan untuk dikembangkan.