Programming Tutorial React Web Development 03 August 2025

7 React Patterns yang Wajib Dikuasai Developer Pemula

7 React Patterns yang Wajib Dikuasai Developer Pemula
Bagikan:

Pernahkah kamu duduk di depan laptop jam 2 pagi, menatap kode React yang kayak mie ayam tanpa bumbu? Spaghetti code yang bikin pusing, useEffect yang nggak jelas, dan UI yang kedip-kedip kayak lampu rusak?

Kalau pernah, selamat datang di klub “Aku Kira Udah Bisa React Ternyata Belum”!

Dulu aku juga begitu. Pikir udah jago React cuma karena bisa useState dan bikin JSX sederhana. Ternyata? Masih jauh panggang dari api. Untuk bisa bikin aplikasi yang bener-bener maintainable dan nggak bikin stress, kamu butuh yang namanya patterns.

Nah, ini dia 7 pola React yang bener-bener ngeubah cara aku coding. Dari developer frustasi jadi developer yang lebih tenang (dan jarang begadang debugging).

Jangan Bikin Component Jadi Tukang Servis

Kamu pasti pernah lihat component yang kayak tukang servis keliling. Dia bisa ngambil data, render UI, handle logic, scroll halaman, bahkan bikin kopi (ok yang terakhir nggak bisa, tapi kamu paham kan).

Stop. Jangan gitu.

Satu component seharusnya fokus ngerjain satu hal aja, tapi ngerjainnya dengan sempurna. Bukan sepuluh hal tapi alakadarnya.

Yang Salah (Jangan Ditiru):

function UserProfile() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  
  useEffect(() => {
    setLoading(true);
    fetchUser()
      .then(setData)
      .catch(setError)
      .finally(() => setLoading(false));
  }, []);
  
  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  
  return (
    <div>
      <h1>{data?.name}</h1>
      <p>{data?.email}</p>
      {/* Dan masih banyak logic lainnya... */}
    </div>
  );
}

Yang Benar (Begini Dong):

// Custom hook untuk handle data
function useUser() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  
  useEffect(() => {
    setLoading(true);
    fetchUser()
      .then(setData)
      .catch(setError)
      .finally(() => setLoading(false));
  }, []);
  
  return { data, loading, error };
}

// Component yang fokus cuma render
function UserProfile() {
  const { data, loading, error } = useUser();
  
  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  
  return (
    <div>
      <h1>{data?.name}</h1>
      <p>{data?.email}</p>
    </div>
  );
}

Lihat bedanya? Sekarang UserProfile cuma fokus render aja. Logic pengambilan data dipisah ke custom hook. Bersih, rapi, dan mudah di-maintain.

Hooks Itu Cuma Function Biasa, Bikin Sendiri Aja

Ingat pertama kali lihat useEffect? Kamu pikir “Wah, ini elegant banget!”

Terus kamu nambahin tiga useEffect, dua useState, dan tiba-tiba component kamu jadi sup kacang merah yang belepotan.

Mari kita luruskan: Hooks itu cuma function biasa. Kamu bisa bikin sendiri. Dan kamu emang harus bikin sendiri!

Custom hooks adalah cheat code-nya React. Serius.

Contoh Custom Hook Sederhana:

// Hook untuk detect lebar window
function useWindowWidth() {
  const [width, setWidth] = useState(
    typeof window !== 'undefined' ? window.innerWidth : 0
  );
  
  useEffect(() => {
    // Function untuk handle resize
    const handleResize = () => setWidth(window.innerWidth);
    
    // Pasang listener
    window.addEventListener('resize', handleResize);
    
    // Jangan lupa bersihin listener pas component unmount
    return () => window.removeEventListener('resize', handleResize);
  }, []);
  
  return width;
}

// Cara pakenya super gampang
function MyComponent() {
  const width = useWindowWidth();
  
  return (
    <div>
      <p>Lebar window: {width}px</p>
      {width < 768 ? <MobileView /> : <DesktopView />}
    </div>
  );
}

Boom! Sekarang kamu punya hook yang bisa dipake di mana-mana. Nggak perlu copas kode yang sama berulang-ulang.

Angkat State, Tapi Jangan Sampai ke Luar Angkasa

Pasti udah denger kan mantra React: “Lift state up!”

Oke, boleh. Tapi ada batasnya.

Kalau parent component kamu mulai kayak pusat kendali NASA, berarti kamu udah ngangkat state terlalu tinggi. State itu harusnya deket sama yang butuh, bukan di atas sana sendirian.

Kamu nggak butuh global state cuma buat kontrol dropdown. Serius, nggak butuh.

Contoh yang Wajar:

// Dropdown state cukup di level ini aja
function UserMenu() {
  const [isOpen, setIsOpen] = useState(false);
  
  return (
    <div>
      <button onClick={() => setIsOpen(!isOpen)}>
        Menu
      </button>
      {isOpen && (
        <ul>
          <li>Profile</li>
          <li>Settings</li>
          <li>Logout</li>
        </ul>
      )}
    </div>
  );
}

// Baru angkat kalau memang perlu dibagi ke component lain
function App() {
  const [user, setUser] = useState(null); // Ini perlu di-share
  
  return (
    <div>
      <Header user={user} />
      <UserMenu /> {/* Dropdown nggak perlu tau soal user */}
    </div>
  );
}

Ingat: state yang deket itu bahagia, state yang jauh itu ribet.

Komposisi Lebih Asik dari Prop Drilling

Capek prop drilling kayak ngebor sumur minyak? Ada solusinya: komposisi.

React punya kekuatan super yang namanya komposisi. Manfaatin, jangan diabaikan.

Daripada Begini (Prop Drilling Hell):

function App() {
  const [user, setUser] = useState(null);
  return <Layout user={user} />;
}

function Layout({ user }) {
  return <Header user={user} />;
}

function Header({ user }) {
  return <UserInfo user={user} />;
}

function UserInfo({ user }) {
  return <span>{user?.name}</span>;
}

Mending Begini (Komposisi yang Bersih):

// Component yang fleksibel
function Modal({ children }) {
  return (
    <div className="modal-backdrop">
      <div className="modal-content">
        {children}
      </div>
    </div>
  );
}

// Cara pakenya
function App() {
  return (
    <Modal>
      <h2>Yakin mau hapus?</h2>
      <button>Ya</button>
      <button>Tidak</button>
    </Modal>
  );
}

Fleksibel, bersih, nggak ada prop acak-acakan. Component kamu jadi kayak LEGO yang bisa disusun sesuka hati.

Render Props Belum Mati Kok

Semua orang ngerasa render props udah mati sejak hooks muncul.

Salah besar. Mereka cuma lagi ngumpet di pojok, nunggu saat yang tepat buat show off.

Render props masih powerful buat case-case tertentu:


```javascript
// Component yang track posisi mouse
function MouseTracker({ render }) {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  
  useEffect(() => {
    const handleMouseMove = (e) => {
      setPos({ x: e.clientX, y: e.clientY });
    };
    
    window.addEventListener("mousemove", handleMouseMove);
    return () => window.removeEventListener("mousemove", handleMouseMove);
  }, []);
  
  return render(pos);
}

// Cara pakenya super fleksibel
function App() {
  return (
    <div>
      <MouseTracker 
        render={({ x, y }) => (
          <p>Mouse ada di posisi {x}, {y}</p>
        )} 
      />
      
      <MouseTracker 
        render={({ x, y }) => (
          <div 
            style={{ 
              position: 'absolute', 
              left: x, 
              top: y,
              background: 'red',
              width: 10,
              height: 10
            }} 
          />
        )} 
      />
    </div>
  );
}

Jangan buang tools cuma karena nggak lagi tren. Kalau masih berguna, ya dipake aja.

Context Buat Setting, Bukan Buat Segalanya

Demi apapun, kalau aku lihat lagi ada yang pake Context buat semua state di aplikasi, aku bakal pindah ke Vue.

Context itu bagus buat hal-hal yang jarang berubah: tema, bahasa, autentikasi. Tapi kalau kamu pake buat state yang sering update?

Selamat datang di neraka performance.

Context yang Wajar:

// Buat tema aplikasi - ini jarang berubah
const ThemeContext = createContext();

function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');
  
  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

// Buat state yang sering berubah, pake state management library
// Atau lebih baik lagi: local state + props
function TodoList() {
  const [todos, setTodos] = useState([]);
  
  return (
    <div>
      <TodoForm onAdd={(todo) => setTodos([...todos, todo])} />
      <TodoItems todos={todos} onToggle={handleToggle} />
    </div>
  );
}

Context buat hal global yang stabil. State biasa buat hal lokal yang dinamis.

useReducer Buat State yang Kompleks

Kalau state kamu udah mulai kayak gini:

const [state, setState] = useState({
  step: 1,
  error: null,
  loading: false,
  data: null,
  filters: {},
  selectedItems: []
});

Saatnya beralih ke useReducer.

useReducer bukan cuma buat yang pake Redux. Ini buat siapa aja yang mau kontrol penuh atas state management.

Dengan useReducer, Hidup Jadi Lebih Teratur:

// Reducer function - semua logic state di satu tempat
function formReducer(state, action) {
  switch (action.type) {
    case "NEXT_STEP":
      return { ...state, step: state.step + 1, error: null };
    
    case "SET_ERROR":
      return { ...state, error: action.payload, loading: false };
    
    case "SET_LOADING":
      return { ...state, loading: action.payload, error: null };
    
    case "SET_DATA":
      return { ...state, data: action.payload, loading: false };
    
    case "RESET":
      return { step: 1, error: null, loading: false, data: null };
    
    default:
      return state;
  }
}

// Component jadi lebih bersih
function MultiStepForm() {
  const [state, dispatch] = useReducer(formReducer, {
    step: 1,
    error: null,
    loading: false,
    data: null
  });
  
  const handleNext = () => {
    dispatch({ type: "NEXT_STEP" });
  };
  
  const handleSubmit = async () => {
    dispatch({ type: "SET_LOADING", payload: true });
    
    try {
      const result = await submitForm();
      dispatch({ type: "SET_DATA", payload: result });
    } catch (error) {
      dispatch({ type: "SET_ERROR", payload: error.message });
    }
  };
  
  return (
    <div>
      {state.loading && <p>Loading...</p>}
      {state.error && <p>Error: {state.error}</p>}
      {/* Form content */}
    </div>
  );
}

Dengan useReducer, semua logic perubahan state ada di satu tempat. Predictable, testable, dan nggak bikin pusing.

Koding Buat Future-You

Pattern-pattern ini nggak cuma bikin aku jadi developer React yang lebih baik. Mereka bikin aku jadi lebih tenang, produktif, dan percaya diri sama kode yang aku tulis.

React memang fleksibel. Kamu bisa bikin abstraksi yang cantik… atau bisa juga bikin tumpukan sampah yang menggunung.

Gunakan patterns. Tulis kode buat future-you yang mungkin lagi mabuk atau kurang tidur. Dan tolong… jangan nested ternary operator.

Tips Bonus Buat Pemula:

  1. Mulai dengan yang sederhana - Jangan langsung kompleks, kuasai dulu konsep dasar
  2. Practice makes perfect - Bikin project kecil-kecil dulu sebelum tackle yang besar
  3. Read the docs - Dokumentasi React itu bagus banget, manfaatin
  4. Join komunitas - Banyak developer React yang siap bantuin di forum/Discord
  5. Don’t overthink - Kalau solusi sederhana udah cukup, nggak perlu yang ribet

Ingat, jadi developer React yang baik itu proses. Nggak ada yang langsung jago. Yang penting konsisten belajar, terus praktek, dan jangan takut salah.

Kamu punya pengalaman seru atau horror story soal React? Share dong di komentar! Aku suka banget dengerin cerita developer lain, terutama yang bikin ketawa atau nangis.

Sekarang, mari kita coding dengan lebih baik. Future-you pasti berterima kasih!