Recraftory

State Management

Pola dan library untuk mengelola state di aplikasi frontend

State management adalah cara mengelola data yang berubah dalam aplikasi dan menyinkronkan tampilan dengan data tersebut.

State Lokal vs Global

State lokal — data yang hanya digunakan satu komponen.

function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}

State global — data yang dibutuhkan banyak komponen di berbagai level.

Ketika prop drilling (passing props melalui banyak layer) menjadi tidak praktis, gunakan state management global.

React Context API

Cukup untuk state global sederhana tanpa update yang sangat sering.

const ThemeContext = createContext("light");

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

function ThemedButton() {
  const { theme, setTheme } = useContext(ThemeContext);
  return <button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>Toggle</button>;
}

Catatan: Context bukan untuk state yang update sangat sering (tiap frame) karena re-render semua consumer.

Zustand

Library ringan dan intuitif.

import { create } from "zustand";

const useStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  reset: () => set({ count: 0 }),
}));

function Counter() {
  const { count, increment } = useStore();
  return <button onClick={increment}>{count}</button>;
}

Fitur: selector untuk mencegah re-render tidak perlu, middleware untuk persist dan devtools.

Redux Toolkit

Pilihan untuk aplikasi kompleks dengan logika state yang rumit.

import { createSlice, configureStore } from "@reduxjs/toolkit";

const counterSlice = createSlice({
  name: "counter",
  initialState: { value: 0 },
  reducers: {
    increment: (state) => { state.value += 1; },
    decrement: (state) => { state.value -= 1; },
  },
});

const store = configureStore({ reducer: counterSlice.reducer });

Keunggulan: time-travel debugging, predictable state updates, middleware ecosystem.

URL sebagai State

Untuk state yang harus shareable dan bookmarkable.

// React Router
const [searchParams, setSearchParams] = useSearchParams();
const filter = searchParams.get("filter") || "all";

// Update URL
setSearchParams({ filter: "active" });

Pola Terbaik

  • Pilih teknologi sesuai kompleksitas: useState → Context → Zustand → Redux
  • Normalisasi state untuk menghindari data duplikat
  • Pisahkan UI state (loading, modal) dari domain state (data dari API)
  • Hindari menyimpan state yang dapat di-derive dari state lain