
Jika kamu baru mulai belajar React JS, kamu pasti akan sering mendengar istilah komponen. Komponen adalah bagian paling dasar dan penting dalam membangun antarmuka pengguna (UI) di React. Bisa dibilang, seluruh aplikasi React adalah kumpulan dari banyak komponen yang bekerja bersama-sama.
Nah, di React sendiri ada dua cara utama untuk membuat komponen: Functional Component dan Class Component. Keduanya bisa digunakan untuk tujuan yang sama, tapi punya gaya penulisan, fitur, dan cara kerja yang sedikit berbeda.
Pada awalnya, Class Component dianggap lebih powerful karena bisa mengelola state dan menggunakan lifecycle methods. Tapi sejak diperkenalkannya React Hooks pada versi 16.8, Functional Component pun jadi sangat fleksibel—bahkan kini lebih direkomendasikan dalam banyak kasus.
Di artikel ini, kita akan:
- Mengenal kedua jenis komponen dengan penjelasan dan contoh kode.
- Membahas perbedaan utama antara Functional dan Class Component.
- Menjelaskan kesalahan umum yang sering terjadi saat menggunakannya.
- Memberikan beberapa best practice agar kamu bisa menulis komponen React dengan lebih baik.
Jadi, kalau kamu masih bingung: “Harus pakai yang mana, Functional atau Class?”, tenang… kita bahas satu per satu dengan contoh nyata.
Persiapan Proyek dan Cara Instalasi
Sebelum kita mulai ngulik komponen di React, tentu kita perlu siapkan dulu proyek React nya, biar bisa langsung praktek dan nggak cuma teori doang.
Syarat Awal
Pastikan kamu udah install Node.js di komputer kamu, minimal versi 14 ya. Buat ngecek, buka terminal atau command prompt terus ketik:
node -v
npm -v
Ini versi yg saya gunakan:

Kalau keluar versinya berarti udah oke, kalo belum, kamu bisa download Node.js dari situs resmi nodejs.org.
Instalasi React dengan Next.js
Nah, buat mulai proyek React, kita bakal pake Next.js. Next.js ini keren banget karena selain React biasa, dia juga punya fitur kayak routing otomatis dan server-side rendering yang bikin performa aplikasi makin ngebut.
Buka terminal terus ketik perintah ini buat bikin proyek baru:
npx create-next-app@latest bwa-react
Jika ada konfirmasi seperti ini tekan Enter di keyboard

- √ Would you like to use TypeScript? ... Pilih Yes
- √ Would you like to use ESLint? ... Pilih Yes
- √ Would you like to use Tailwind CSS? ... Pilh Yes
- √ Would you like your code inside a
src/
directory? ... Pilih Yes - √ Would you like to use App Router? (recommended) ... Pilih Yes
- √ Would you like to use Turbopack for
next dev
? ... Pilih Yes - √ Would you like to customize the import alias (
@/*
by default)? ... Pilih No

Jika proses intallasi sudah selesai, masuk ke folder proyeknya:
cd bwa-react
Terus jalankan development server dengan perintah:
npm run dev

Biasanya bakal keluar alamat http://localhost:3000
di terminal. Kamu buka alamat itu di browser, dan… voila! Kamu udah punya proyek React dengan Next.js siap pakai.

Kalau kamu pake bun, tinggal ganti aja npm
jadi bun
di perintah-perintah tadi.
Mengenal Komponen di React
Oke, sekarang saatnya masuk ke inti dari pembahasan kita: komponen. Jadi, di React, semua hal yang tampil di layar itu sebenernya dibangun dari komponen. Mulai dari tombol, teks, gambar, sampai halaman penuh semuanya komponen.
Apa itu Komponen?
Komponen itu bisa dibilang kayak "blok bangunan" dari UI aplikasi kita. Dia bisa dipake ulang, bisa dikasih data, dan bisa saling terhubung satu sama lain. Ibaratnya kayak LEGO, kamu gabungin banyak potongan kecil jadi satu bentuk utuh.
Ada dua jenis utama komponen di React:
- Functional Component (alias komponen fungsi)
- Class Component (alias komponen kelas)
Keduanya bisa dipake buat hal yang sama, tapi punya gaya nulis yang beda dan cara kerja yang sedikit… ya beda dikit lah.
Functional Component
Functional Component ditulis sebagai fungsi JavaScript biasa. Sejak adanya Hooks, Functional Component bisa ngelakuin hampir semua hal yang dulu cuma bisa di Class Component.
Contoh sederhana:
// components/HelloFunctional.tsx
type HelloProps = {
name: string;
};
function HelloFunctional(props: HelloProps) {
return <h1>Halo, {props.name}!</h1>;
}
export default HelloFunctional;
Atau bisa juga pake arrow function (lebih modern):
// components/HelloFunctionalArrow.tsx
type HelloProps = {
name: string;
};
const HelloFunctional: React.FC<HelloProps> = ({ name }) => {
return <h1>Halo, {name}!</h1>;
};
export default HelloFunctional;
Class Component
Dulu, sebelum Hooks muncul, kalo kamu mau pake state
atau lifecycle method, kamu harus pake Class Component.
Contoh:
// components/HelloClass.tsx
import { Component } from 'react';
type HelloProps = {
name: string;
};
class HelloClass extends Component<HelloProps> {
render() {
return <h1>Halo, {this.props.name}!</h1>;
}
}
export default HelloClass;
Tapi sekarang, Class Component udah jarang dipake di proyek baru. Bukan berarti dilarang ya, cuma tren-nya udah beralih ke Functional Component.
Perbandingan Singkat
Fitur | Functional Component | Class Component |
---|---|---|
Penulisan | Lebih ringkas & simple | Lebih verbose |
State & lifecycle | Pakai Hooks | Pakai this.state & this.setState |
Kode reuse | Lebih mudah dengan Hooks | Lebih terbatas |
Popularitas sekarang | Sangat direkomendasikan | Masih dipakai di proyek lama |
Masih bingung pilih yang mana? Tenang, kita bakal bahas lebih lanjut soal perbedaan dan kapan sebaiknya pake yang mana.
Perbedaan Utama Functional vs Class Component
Meski sama-sama bisa dipake buat bikin tampilan, ada beberapa perbedaan penting antara Functional Component dan Class Component. Biar nggak bingung, kita bahas satu-satu ya.
Penulisan (Sintaks)
Functional Component itu lebih ringkas. Cukup nulis fungsi, langsung return elemen JSX.
// Functional
const Hello = () => <h1>Hello, World!</h1>;
Bandingin sama Class Component:
// Class
class Hello extends React.Component {
render() {
return <h1>Hello, World!</h1>;
}
}
Liat kan? Class Component butuh lebih banyak baris buat hal yang sebenernya sama aja.
Mengelola State
Functional Component sekarang udah bisa pake Hooks buat ngatur state.
import { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>Jumlah: {count}</p>
<button onClick={() => setCount(count + 1)}>Tambah</button>
</div>
);
};
export default Counter;
Dulu (dan masih bisa), kalo mau pake state harus pake Class Component:
// components/CounterClass.tsx
import { Component } from 'react';
type CounterState = {
count: number;
};
class CounterClass extends Component<{}, CounterState> {
constructor(props: {}) {
super(props);
this.state = { count: 0 };
}
handleTambah = () => {
this.setState((prev) => ({ count: prev.count + 1 }));
};
render() {
return (
<div>
<p>Jumlah: {this.state.count}</p>
<button onClick={this.handleTambah}>Tambah</button>
</div>
);
}
}
export default CounterClass;
Agak panjang ya 😅
Lifecycle
Class Component punya lifecycle methods kayak componentDidMount
, componentDidUpdate
, dll.
componentDidMount() {
console.log('Component muncul ke layar!');
}
Tapi di Functional Component, kamu bisa ngelakuin hal yang sama pake useEffect
:
import { useEffect } from 'react';
useEffect(() => {
console.log('Komponen dimuat ke layar!');
}, []);
Sama fungsinya, tapi jauh lebih simpel dan fleksibel.
Konteks “this”
Di Class Component, kamu sering harus berurusan sama this
, dan itu bisa bikin pusing.
this.setState(...);
this.props.nama;
Sementara di Functional Component, semuanya lebih clean—nggak perlu mikir soal this
.
Performance?
Secara performa, dua-duanya hampir sama di kebanyakan kasus. Tapi karena Functional Component lebih ringan dan mudah dioptimasi (terutama dengan React 18 dan concurrent mode), biasanya jadi pilihan utama buat proyek baru.
Singkatnya:
- Proyek baru? Functional Component + Hooks adalah best choice.
- Ngurusin proyek lama? Kadang masih ketemu Class Component, dan itu gapapa.
- Mau belajar dua-duanya? Bagus! Jadi kamu ngerti semua ekosistem React.
Contoh Kode Lengkap Functional vs Class Component
Studi Kasus:
Kita mau bikin komponen UserProfile
yang:
- Nampilin nama & email pengguna
- Bisa toggle status login (on/off)
Functional Component (dengan Hooks)
// components/UserProfileFunctional.tsx
import { Component } from "react";
type UserProfileProps = {
name: string;
email: string;
};
type UserProfileState = {
loggedIn: boolean;
};
class UserProfileClass extends Component<UserProfileProps, UserProfileState> {
constructor(props: UserProfileProps) {
super(props);
this.state = {
loggedIn: false,
};
}
toggleLogin = () => {
this.setState((prev) => ({
loggedIn: !prev.loggedIn,
}));
};
render() {
const { name, email } = this.props;
const { loggedIn } = this.state;
const statusClass = `rounded-full h-10 w-10 ${
loggedIn ? "bg-green-500" : "bg-red-500"
}`;
const btnClass = `mt-4 px-4 py-1.5 cursor-pointer rounded-full text-white font-bold ${
loggedIn ? "bg-red-300" : "bg-blue-400"
}`;
return (
<div className="flex flex-col gap-2 border-2 p-4 rounded-2xl">
<div className="flex gap-2.5 items-center">
<div className={statusClass}></div>
<div className="flex flex-col">
<h2 className="font-bold">{name}</h2>
<p className="opacity-80 text-[14px]">{email}</p>
</div>
</div>
<button onClick={this.toggleLogin} className={btnClass}>
{loggedIn ? "Logout" : "Login"}
</button>
</div>
);
}
}
export default UserProfileClass;
🟢 Kelebihan:
- Ringkas dan gampang dibaca
- Gunain
useState
buat handle login - Nggak repot sama
this
Class Component (dengan state & event)
// components/UserProfileClass.tsx
import { Component } from "react";
type UserProfileProps = {
name: string;
email: string;
};
type UserProfileState = {
loggedIn: boolean;
};
class UserProfileClass extends Component<UserProfileProps, UserProfileState> {
constructor(props: UserProfileProps) {
super(props);
this.state = {
loggedIn: false,
};
}
toggleLogin = () => {
this.setState((prev) => ({
loggedIn: !prev.loggedIn,
}));
};
render() {
const { name, email } = this.props;
const { loggedIn } = this.state;
const statusClass = `rounded-full h-10 w-10 ${
loggedIn ? "bg-green-500" : "bg-red-500"
}`;
const btnClass = `mt-4 px-4 py-1.5 cursor-pointer rounded-full text-white font-bold ${
loggedIn ? "bg-red-300" : "bg-blue-400"
}`;
return (
<div className="flex flex-col gap-2 border-2 p-4 rounded-2xl">
<div className="flex gap-2.5 items-center">
<div className={statusClass}></div>
<div className="flex flex-col">
<h2 className="font-bold">{name}</h2>
<p className="opacity-80 text-[14px]">{email}</p>
</div>
</div>
<button onClick={this.toggleLogin} className={btnClass}>
{loggedIn ? "Logout" : "Login"}
</button>
</div>
);
}
}
export default UserProfileClass;
🔴 Kekurangan:
- Lebih verbose
- Perlu constructor &
this
buat handle event & state
Jika kalian mendapatkan error seperti berikut, itu karena defaultnya di Next.js semua komponen itu menggunakan server comonent, dan useState itu hanya bisa digunakan di client component. Kalian bisa belajar tentang server component dan client component pada postingan BuildWithAngga tentang Tutorial Next.js 15 Belajar Server dan Client Component Projek Web Booking Hotel.

Untuk mengatasi ini, kita tinggal tambahkan "use client"
pada baris pertama kode, jadinya seperti ini:
"use client";
import { Component } from "react";
type UserProfileProps = {
name: string;
email: string;
};
type UserProfileState = {
loggedIn: boolean;
};
class UserProfileClass extends Component<UserProfileProps, UserProfileState> {
constructor(props: UserProfileProps) {
super(props);
this.state = {
loggedIn: false,
};
}
toggleLogin = () => {
this.setState((prev) => ({
loggedIn: !prev.loggedIn,
}));
};
render() {
const { name, email } = this.props;
const { loggedIn } = this.state;
const statusClass = `rounded-full h-10 w-10 ${
loggedIn ? "bg-green-500" : "bg-red-500"
}`;
const btnClass = `mt-4 px-4 py-1.5 cursor-pointer rounded-full text-white font-bold ${
loggedIn ? "bg-red-300" : "bg-blue-400"
}`;
return (
<div className="flex flex-col gap-2 border-2 p-4 rounded-2xl">
<div className="flex gap-2.5 items-center">
<div className={statusClass}></div>
<div className="flex flex-col">
<h2 className="font-bold">{name}</h2>
<p className="opacity-80 text-[14px]">{email}</p>
</div>
</div>
<button onClick={this.toggleLogin} className={btnClass}>
{loggedIn ? "Logout" : "Login"}
</button>
</div>
);
}
}
export default UserProfileClass;
Tambahkan juga "use client"
pada UserProfileClass.tsx.
Buka page.tsx lalu ubah jadi seperti ini:
import UserProfileClass from "@/components/UserProfileClass";
import UserProfileFunctional from "@/components/UserProfileFunctional";
export default function Home() {
return (
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
<main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start">
<h3 className="text-2xl font-bold">Functional Component:</h3>
<UserProfileFunctional
name="Taufan Fatahillah"
email="[email protected]"
/>
<h3 className="text-2xl font-bold">Class Component:</h3>
<UserProfileClass name="Jonh Doe" email="[email protected]" />
</main>
</div>
);
}
Hasilnya akan seperti ini:

Catatan Tambahan
- Untuk proyek baru, disarankan pake Functional Component + Hooks
- Tapi belajar Class Component tetep penting kalau kamu ketemu kode lama (legacy code)
Kesalahan Umum yang Harus Dihindari
Walaupun React keliatannya simpel, tapi banyak juga jebakan yang sering bikin frustrasi. Nih, beberapa kesalahan umum yang sering kejadian:
Lupa Typing Props
Ini klasik banget. Di TypeScript, semua props harus didefinisiin typenya. Kalau nggak, kamu bakal kehilangan auto-complete dan bisa bikin bug susah dilacak.
// ❌ Salah (nggak ada type)
function Greet(props) {
return <p>Hi, {props.name}</p>;
}
// ✅ Benar
type GreetProps = {
name: string;
};
function Greet({ name }: GreetProps) {
return <p>Hi, {name}</p>;
}
Gunain any
terus-terusan
Pakai any
itu kayak ngilangin fitur utama TypeScript. Kalau sering pakai any
, sama aja kayak balik ke JavaScript biasa 😅
// ❌ Salah
const handleClick = (e: any) => {
console.log(e.target.value);
};
// ✅ Benar
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
console.log(e.currentTarget.value);
};
State di Functional Component Tanpa Tipe
React bisa nebak tipenya sih, tapi kalau datanya kompleks, sebaiknya tetap definisiin tipe-nya.
// ❌ Salah
const [user, setUser] = useState(null);
// ✅ Benar
type User = {
name: string;
age: number;
};
const [user, setUser] = useState<User | null>(null);
Mengakses this
di Functional Component
Kadang yang baru pindah dari Class suka iseng nulis this.props
di Functional 🤦
// ❌ Salah
const MyComponent = () => {
console.log(this.props); // ini pasti error
};
Import React tapi nggak dipakai
Sejak React 17, kamu nggak wajib import React
di file yang pakai JSX. Tapi kadang orang masih nulis ini padahal gak perlu.
// ❌ Nggak perlu kalau nggak pakai React secara eksplisit
import React from 'react';
Best Practices dalam Menulis Komponen React + TypeScript
Nah, biar kode kamu clean, maintainable, dan scalable, coba terapin beberapa best practice berikut:
Pisahin Tipe Props ke File Sendiri (kalau kompleks)
Kalau props-nya banyak atau dipakai di banyak komponen, lebih baik dipisah ke file types.ts
.
// types/User.ts
export type User = {
name: string;
email: string;
};
// components/UserCard.tsx
import { User } from '@/types/User';
const UserCard = ({ name, email }: User) => {
return <div>{name} - {email}</div>;
};
Gunain Destructuring Props
Lebih rapi dan enak dibaca dibanding props.name
, props.email
, dst.
// ✅ Lebih clean
const Profile = ({ name, age }: { name: string; age: number }) => {
return <p>{name} - {age}</p>;
};
Selalu Type State dengan Jelas
Daripada ngandelin inferensi TypeScript, lebih baik kamu tegasin typenya, apalagi kalau datanya nullable atau array.
const [todos, setTodos] = useState<TodoItem[]>([]);
Gunain React.FC
untuk Komponen Simpel
Kalau komponen kamu cuma pake props bawaan, React.FC
bisa ngebantu banyak (auto children
, auto typing props):
type AlertProps = {
message: string;
};
const Alert: React.FC<AlertProps> = ({ message, children }) => {
return <div>{message} {children}</div>;
};
Break Down Komponen Jadi Kecil-kecil
Jangan bikin satu komponen isinya ribuan baris. Pisah jadi komponen kecil yang reusable.
// components/Post.tsx
const Post = ({ title, author }: { title: string; author: string }) => (
<article>
<h2>{title}</h2>
<small>by {author}</small>
</article>
);
Gunakan ESLint + Prettier + TypeScript Strict Mode
Biar kode kamu tetap bersih, konsisten, dan minim bug dari awal.
ESLint – Linting Code JavaScript/TypeScript
ESLint itu semacam "pengawas" kode kita. Dia bantu nyari dan ngasih warning/error kalau ada potensi bug atau style yang nggak konsisten. Contoh:
const a = 5
console.log(a)
Tanpa ESLint:
- Kode di atas dianggap sah-sah aja.
Dengan ESLint:
- Bisa dikasih warning karena
console.log
, titik koma, atau penamaan variabel nggak sesuai aturan.
Prettier – Code Formatter Otomatis
Prettier fokus ke formatting, bukan logic. Dia bantu rapihin kode secara otomatis. Misalnya:
const hello = (name:string)=>{return "Hi "+name}
Setelah Prettier:
const hello = (name: string) => {
return "Hi " + name;
};
Auto rapi, konsisten, dan bikin kode enak dibaca tim 😎
TypeScript Strict Mode – Type Safety Ketat
strict: true
di tsconfig.json
artinya kamu bilang ke TypeScript:
"Bro, tolong pastiin semua variable, return type, props, dsb harus jelas dan aman ya!”
Contoh:
// Tanpa strict mode
function greet(name) {
return 'Hello ' + name;
}
// Dengan strict mode
function greet(name: string): string {
return 'Hello ' + name;
}
Hasilnya: Lebih sedikit bug, lebih pede deploy 🚀
Next.js Include ESLint by Default
Kalau kamu bikin proyek Next.js baru (npx create-next-app
), Next.js bakal langsung nanya:
"Mau aktifin ESLint?"
Dan kalau kamu klik "Yes", dia bakal:
- Auto install ESLint
- Tambah file
.eslintrc.json
- Konfig yang cocok buat Next.js
Kamu tinggal pakai aja tanpa setup ribet!
Bonus: Gabungin Semuanya
Untuk workflow terbaik, kamu bisa gabungin keempatnya:
- ✅ ESLint → cek kode logic & style
- ✨ Prettier → rapihin format otomatis
- 🔐 TypeScript Strict → jaga keamanan dan kejelasan data
- ⚡ Next.js → tinggal pake, udah include tools-nya
Perbandingan Singkat Functional vs Class Component (Tabel)
Aspek | Functional Component | Class Component |
---|---|---|
Sintaks | Fungsi biasa atau arrow function | Menggunakan class dan extends React.Component |
State | Gunakan useState | Gunakan this.state dan this.setState |
Lifecycle Method | Gunakan useEffect | Gunakan componentDidMount , componentDidUpdate , dll |
Hooks Support | ✅ Ya | ❌ Tidak |
Binding this | ❌ Tidak perlu | ✅ Perlu |
Kode lebih ringkas | ✅ Umumnya lebih ringkas | ❌ Lebih verbose |
Digunakan di proyek baru | ✅ Sangat disarankan | ❌ Jarang, kecuali legacy |
Dukungan TypeScript | ✅ Sangat baik | ✅ Tapi butuh lebih banyak kode |
Kapan Sebaiknya Pakai Functional vs Class?
Gunakan Functional Component jika:
- Kamu baru belajar React (lebih simpel dan modern)
- Proyek baru menggunakan React 16.8+
- Ingin menggunakan Hooks seperti
useState
,useEffect
,useContext
, dll - Ingin kode lebih singkat dan mudah dibaca
- Ingin mengikuti best practice terbaru
Gunakan Class Component jika:
- Kamu sedang maintenance proyek lama
- Proyek menggunakan React versi lama (di bawah 16.8)
- Komponen sudah sangat besar dan susah untuk diubah total ke function
Tapi secara umum, Functional Component adalah standar modern React. Bahkan tim React sendiri merekomendasikan penggunaan fungsi ketimbang class.
Penutup
Di artikel ini, kita udah bahas lumayan lengkap tentang:
- Apa itu Functional dan Class Component di React
- Cara setup proyek Next.js + TypeScript
- Contoh kode untuk dua jenis komponen
- ❌ Kesalahan umum yang sering kejadian
- ✅ Best practices biar kode lebih rapi dan scalable
- 📌 Perbandingan dan kapan sebaiknya digunakan