Menu

Hook useState di React: Contoh dan Kesalahan Umum

useState memberi komponen sebuah nilai yang bertahan melewati render ulang dan setter yang menggambar ulang layar saat nilainya berubah. Pelajari sintaksnya, fungsi updater, object dan array di state, dan mengapa sebuah nilai terlihat usang tepat setelah kamu mengaturnya.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

useState adalah hook yang membuat komponen bisa mengingat sesuatu di antara render: sebuah hitungan, teks di input, apakah sebuah menu sedang terbuka. Setiap kali kamu memanggil setter-nya, React merender komponen itu lagi dengan nilai yang baru.

Klik tombolnya, lalu ganti useState(0) menjadi useState(10) di editor. Pratinjau dibangun ulang dan hitungannya dimulai dari 10.

Sintaksnya

const [value, setValue] = useState(initialValue);
  • initialValue hanya dipakai di render pertama. Di setiap render berikutnya, React mengabaikannya dan mengembalikan nilai yang disimpannya.
  • value adalah nilai saat ini untuk render ini.
  • setValue mengganti nilainya dan menjadwalkan render baru.

Namanya bebas kamu tentukan. useState mengembalikan array dua item dan kurung siku membongkarnya, jadi [isOpen, setIsOpen] dan [email, setEmail] adalah pola yang sama.

Panggil useState di tingkat teratas komponenmu, jangan pernah di dalam perulangan, kondisi, atau fungsi bersarang. React mencocokkan setiap pemanggilan dengan nilai yang disimpannya berdasarkan urutan pemanggilan, jadi urutan itu harus sama di setiap render (lihat aturan hook).

Beberapa state sekaligus

Sebuah komponen bisa memanggil useState sebanyak yang dibutuhkannya. Setiap pemanggilan adalah nilai tersendiri yang tidak saling bergantung.

State adalah snapshot

Setter tidak mengubah variabel yang sedang kamu pegang. Setter memberi tahu React berapa seharusnya nilainya di render berikutnya. Sampai render itu terjadi, render saat ini tetap melihat nilai lama.

Buka console di bawah pratinjau dan klik sekali. Handler mencatat 0, nilai lama, lalu komponen mencatat render baru dengan 1. Tidak ada yang salah: count adalah konstanta selama seluruh render, dan render berikutnya mendapat nilai yang baru.

Fungsi updater

Karena snapshot itu, memanggil setter tiga kali dengan count + 1 hanya menambah satu, bukan tiga: setiap pemanggilan menghitung 0 + 1. Berikan sebuah fungsi, dan React memberikan hasil pemanggilan sebelumnya ke setiap pemanggilan.

Pakai bentuk updater setiap kali nilai berikutnya bergantung pada nilai sebelumnya dan pembaruannya mungkin tidak berjalan langsung dari render terbaru: beberapa set di satu handler, callback setInterval, atau effect.

Object dan array di state

React memutuskan apakah perlu merender lagi dengan membandingkan nilai lama dan baru memakai Object.is. Kalau kamu mengubah object di tempat dan mengirim object yang sama kembali, perbandingannya menyatakan tidak ada yang berubah dan layar tetap seperti semula. Selalu berikan object atau array yang baru.

{ ...user, age: user.age + 1 } menyalin setiap field dan menimpa satu di antaranya. [...tags, 'code'] menambahkan satu item, dan filter menghapus satu, keduanya mengembalikan array baru. Halaman tentang memperbarui array dan object membahas object bersarang, mengedit satu item di daftar, dan menyisipkan di tengah.

State awal lazy

Argumen untuk useState dievaluasi di setiap render, meskipun React hanya memakainya pertama kali. Saat menghitungnya itu berat (membaca localStorage, mem-parsing string yang besar), berikan sebuah fungsi. React memanggilnya sekali, di render pertama.

// Runs readSavedNotes() on every render, then throws the result away
const [notes, setNotes] = useState(readSavedNotes());

// Runs it once
const [notes, setNotes] = useState(readSavedNotes);
const [notes, setNotes] = useState(() => readSavedNotes());

Mereset state dengan key

State adalah milik posisi sebuah komponen di pohon. Kalau kamu merender key yang berbeda di tempat yang sama, React menganggapnya sebagai komponen baru dan state-nya dimulai dari awal. Ini cara paling rapi untuk mereset formulir saat hal yang sedang diedit berganti.

Ketik sebuah pesan, lalu ganti penerimanya: draft-nya terhapus. Hapus key={to} lalu coba lagi, dan teksnya tetap ada, karena React sekarang melihat Draft yang sama di tempat yang sama.

Kesalahan umum

Mencatat state tepat setelah mengaturnya. Kamu melihat nilai lama, seperti yang ditunjukkan di atas. Catat di badan komponen, atau hitung nilai berikutnya ke sebuah variabel lebih dulu lalu pakai variabel itu.

Memutasi state. user.age++; setUser(user) mengirim object yang sama, jadi tidak ada yang dirender. Salin dulu.

Memanggil setter saat render. <button onClick={setCount(count + 1)}> memanggil setCount saat merender, yang memicu render lagi, yang memanggilnya lagi. React menghentikan perulangan ini dengan "Too many re-renders". Berikan sebuah fungsi: onClick={() => setCount(count + 1)}.

Menyimpan nilai yang bisa dihitung. Kalau fullName selalu first + ' ' + last, hitung saat render alih-alih menyimpan state ketiga yang bisa tidak sinkron.

Pertanyaan yang sering diajukan

Apa yang dikembalikan useState?

Array berisi tepat dua item: nilai saat ini dan fungsi yang menggantinya. Kamu sendiri yang memberi nama keduanya dengan array destructuring, menurut konvensi [thing, setThing].

Mengapa state saya tidak langsung diperbarui?

Memanggil setter tidak mengubah variabel yang sudah kamu pegang. Setter meminta React merender komponen itu lagi, dan nilai baru muncul di render berikutnya. Di dalam event handler saat ini, nilai lama masih berlaku, jadi console.log(count) tepat setelah setCount(count + 1) mencetak angka yang lama.

Kapan sebaiknya memberikan fungsi ke setter?

Saat nilai baru bergantung pada nilai lama dan kamu mengaturnya lebih dari sekali, atau dari dalam timer atau effect. setCount(c => c + 1) selalu dimulai dari nilai terbaru, sedangkan setCount(count + 1) dimulai dari nilai yang dilihat render ini.

Bisakah useState menyimpan object atau array?

Bisa, tapi perlakukan sebagai read only. Buat object atau array baru lalu berikan ke setter (setUser({ ...user, name }), setItems([...items, item])). Mengubah yang sudah ada di tempat tidak memicu render.

Apa bedanya useState dan useReducer?

Keduanya menyimpan state. useState cocok untuk beberapa nilai yang berdiri sendiri. useReducer memindahkan logika pembaruan ke satu fungsi yang menerima action, yang lebih mudah dibaca saat banyak event mengubah state yang sama dengan cara yang saling berkaitan.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai