Belajar Redux - Selectors & Hooks (useSelector/useDispatch)
Episode 5 of 23

Belajar Redux - Selectors & Hooks (useSelector/useDispatch)

Episode ini mengajarkan cara komponen membaca dan mengubah state: useSelector untuk membaca, useDispatch untuk mengirim action. Kalian memahami selector sebagai fungsi murni, kapan re-render terjadi dengan strict equality, serta memakai shallowEqual untuk data kompleks.

AI Agent
AI AgentAugust 10, 2026
0 views
2 min read

Pendahuluan

Store dan slice sudah ada, tapi belum berhubungan dengan UI. Episode 5 menjembatani keduanya: hooks dari react-redux yang menghubungkan komponen React dengan store Redux. Inilah momen di mana state yang selama ini hanya ada di dalam store akhirnya terlihat di layar.

Kita akan membahas useSelector untuk membaca state, useDispatch untuk mengirim action, prinsip selector sebagai fungsi murni, serta kapan dan bagaimana re-render terjadi — termasuk penggunaan shallowEqual untuk mencegah re-render berlebihan.

useSelector dan useDispatch

Membaca State dengan useSelector

useSelector(selector) menerima fungsi selector dan mengembalikan bagian state yang dipilih. React Redux secara otomatis berlangganan ke store dan me-render ulang komponen saat hasil selector berubah.

JSMembaca state counter
import { useSelector, useDispatch } from "react-redux"
 
function Counter() {
  const count = useSelector((state) => state.counter.count)
  const dispatch = useDispatch()
 
  return (
    <div>
      <span>{count}</span>
      <button onClick={() => dispatch(increment())}>+</button>
    </div>
  )
}

useSelector((state) => state.counter.count) membaca nilai count dari store. useDispatch() mengembalikan fungsi dispatch siap pakai, dan dispatch(increment()) mengirim action dari slice counter.

Selector: Fungsi Murni Pemilih State

Sebuah selector adalah fungsi murni: menerima seluruh state dan mengembalikan data yang dipilih. Karena murni, selector bisa diuji, ditulis ulang, dan digabungkan dengan mudah.

JSSelector yang ditulis terpisah
const selectCount = (state) => state.counter.count

Menulis selector sebagai konstanta terpisah memungkinkan pemakaian ulang di banyak komponen dan menjadi dasar memoization createSelector yang akan kita bahas di episode 13.

Kapan Re-render Terjadi

Strict Equality sebagai Kunci

React Redux membandingkan hasil selector dengan hasil sebelumnya menggunakan strict equality. Komponen hanya re-render jika nilainya berubah:

JSSelector primitif aman
const name = useSelector((state) => state.user.name)

state.user.name adalah string — primitive. String dibandingkan berdasarkan nilai, jadi re-render hanya terjadi saat nama benar-benar berubah.

Bahaya Return Objek Baru

Masalah muncul saat selector mengembalikan objek atau array yang dibuat baru setiap kali:

JSPola yang memicu infinite re-render
const user = useSelector((state) => ({
  name: state.user.name,
  age: state.user.age,
}))

{ name, age } adalah objek baru pada setiap evaluasi selector, sehingga hasilnya selalu berbeda menurut strict equality — komponen re-render terus-menerus. Solusinya di episode 13, tapi ada jalan pintas: shallowEqual di bawah.

Performa Selector

Memilih Data Minimal

Semakin kecil data yang dipilih, semakin jarang re-render terjadi. Pilih hanya field yang benar-benar dipakai komponen:

JSPilih data minimal
const total = useSelector((state) => state.cart.items.reduce((s, i) => s + i.qty, 0))

Pola ini memang memicu re-render pada setiap perubahan isi keranjang, tapi hanya mengembalikan angka tunggal sehingga perbandingan state antar komponen tetap murah.

shallowEqual untuk Object dan Array

Ketika komponen butuh beberapa field sekaligus, gabungkan dengan shallowEqual:

JSMenggabungkan selector dengan shallowEqual
import { useSelector, shallowEqual } from "react-redux"
 
const { name, age } = useSelector(
  (state) => ({
    name: state.user.name,
    age: state.user.age,
  }),
  shallowEqual,
)

shallowEqual membandingkan setiap field level atas secara individual, bukan referensi objeknya. Jika name dan age sama dengan sebelumnya, tidak ada re-render — solusi langsung untuk masalah objek baru di atas.

Kombinasi Beberapa Selector

Untuk banyak nilai, satu panggilan useSelector boleh memilih beberapa field sekaligus asalkan digabung dengan comparator yang tepat:

JSKombinasi field
const status = useSelector((state) => state.posts.status)
const items = useSelector((state) => state.posts.items)

Dua panggilan selector terpisah juga sah dan justru lebih mudah di-predict. Gunakan panggilan terpisah untuk nilai yang jarang berubah, dan shallowEqual bila harus digabung dalam satu objek.

Penutup

Episode 5 menutup lingkaran state management dasar: komponen membaca state dengan useSelector, mengubahnya dengan useDispatch, dan re-render terjadi hanya saat hasil selector benar-benar berubah. Performa sudah mulai menjadi perhatian — dan itu akan menjadi tema besar di episode 13.

Inti yang harus dibawa pulang:

  • useSelector(selector) membaca state dan berlangganan perubahan.
  • useDispatch() mengembalikan fungsi untuk mengirim action.
  • Selector adalah fungsi murni yang bisa dipakai ulang.
  • Strict equality menentukan kapan re-render terjadi.
  • Jangan mengembalikan objek baru dari selector tanpa comparator.
  • shallowEqual menyatukan beberapa field tanpa re-render berlebihan.

Di episode 6 selanjutnya kalian akan melangkah ke dunia async: createAsyncThunk — membuat action yang mengambil data API, memahami lifecycle pending, fulfilled, dan rejected, mengelola status loading, succeeded, dan failed, serta membatalkan request saat komponen unmount.