useState
useState
merupakan React Hook yang memungkinkan Anda untuk menambahkan variabel state pada komponen Anda.
const [state, setState] = useState(initialState);
- Referensi
- Penggunaan
- Pemecahan masalah
- Saya sudah memperbarui state, tetapi saat saya mencetak log nilainya masih yang lama
- Saya telah memperbarui state, tetapi tidak ada perbaruan pada layar
- Saya mendapatkan galat: “Too many re-renders”
- Fungsi inisialisasi atau pembaruan saya berjalan dua kali
- Saya mencoba mengatur state ke sebuah fungsi, namun malah dipanggil
Referensi
useState(initialState)
Panggil fungsi useState
di tingkat atas komponen Anda untuk mendeklarasikan sebuah variabel state.
import { useState } from 'react';
function MyComponent() {
const [age, setAge] = useState(28);
const [name, setName] = useState('Taylor');
const [todos, setTodos] = useState(() => createTodos());
// ...
Konvensi dalam menamai variable state adalah menggunakan pola [something, setSomething]
dengan array destructuring.
Lihat lebih banyak contoh di bawah ini.
Parameter
initialState
: Nilai awal pada sebuah state. Nilainya dapat berupa jenis apa saja, namun terdapat perilaku khusus untuk fungsi. Argumen ini diabaikan setelah rendering awal.- Jika Anda mengoper sebuah fungsi sebagai
initialState
, itu akan diperlakukan sebagai fungsi inisialisasi (initializer function). Fungsi tersebut harus murni (pure), tidak boleh menerima argumen, dan harus mengembalikan nilai dengan tipe apa pun. React akan memanggil fungsi inisialisasi ketika menginisialisasi komponen, dan menyimpan nilai kembaliannya sebagai state awal. Lihat contoh lainnya di bawah ini.
- Jika Anda mengoper sebuah fungsi sebagai
Kembalian
useState
mengembalikan sebuah senarai yang memiliki dua nilai:
- State saat ini. Pada saat pertama kali render, itu akan sama dengan
initialState
yang Anda oper sebelumnya. - Fungsi
set
function yang memungkinkan Anda memperbarui state menjadi nilai yang berbeda dan memicu pembaruan ulang (re-render).
Catatan Penting
useState
merupakan sebuah Hook, sehingga Anda hanya dapat memanggilnya di level atas komponen Anda atau Hooks Anda sendiri. Anda tidak dapat memanggilnya di dalam perulangan atau kondisi. Jika Anda membutuhkannya, Anda dapat membuat komponen baru dan pindahkan state ke dalamnya.- Dalam mode ketat (Strict Mode), React akan memanggil fungsi inisialisasi Anda dua kali untuk membantu Anda menemukan kejadian yang tidak diharapkan. Hal ini hanya terjadi pada pengembangan dan tidak mempengaruhi produksi. Jika initializer function Anda murni (sebagaimana mestinya), ini seharusnya tidak mempengaruhi perilakunya. Hasil dari salah satu pemanggilan akan diabaikan.
Fungsi set
, seperti setSomething(nextState)
Fungsi set
yang dikembalikan oleh useState
memungkinkan Anda memperbarui state ke nilai yang berbeda dan memicu pembaruan ulang (re-render). Anda dapat mengoper state berikutnya secara langsung, atau sebuah fungsi yang akan mengkalkulasi dari state sebelumnya:
const [name, setName] = useState('Edward');
function handleClick() {
setName('Taylor');
setAge(a => a + 1);
// ...
Parameter
nextState
: Nilai yang Anda inginkan untuk menjadi state berikutnya. Ini dapat berupa nilai dari jenis apa pun, tetapi ada perilaku khusus untuk sebuah fungsi.- Jika Anda mengoper sebuah fungsi sebagai
nextState
, itu akan diperlakukan sebagai fungsi pembaruan (updater function). Fungsi ini harus murni (pure), hanya menerima state yang tertunda sebagai argumen satu-satunya, dan harus mengembalikan state berikutnya. React akan menempatkan fungsi pembaruan Anda dalam antrian dan memperbarui ulang komponen Anda. Selama render berikutnya, React akan mengkalkulasi state berikutnya dengan menerapkan semua pembaruan dalam antrian ke state sebelumnya Lihat contoh lainnya di bawah ini.
- Jika Anda mengoper sebuah fungsi sebagai
Kembalian
Fungsi set
tidak memiliki nilai kembalian.
Catatan Penting
-
Fungsi
set
hanya memperbarui variabel state ketika render berikutnya. Jika Anda membaca variabel state setelah memanggil fungsiset
, Anda akan tetap mendapatkan nilai lama yang ada di layar sebelum pemanggilan Anda. -
Jika nilai baru yang Anda berikan identik dengan
state
saat ini, seperti yang ditentukan oleh perbandinganObject.is
, React akan melewatkan proses pembaruan ulang komponen dan anak-anaknya Ini merupakan sebulah optimisasi. Meskipun dalam beberapa kasus React mungkin masih perlu memanggil komponen Anda sebelum melewatkan anak-anaknya, ini seharusnya tidak mempengaruhi kode Anda. -
React pembaruan state berkelompok. Fungsi
set
akan memperbarui tampilan setelah semua event handler selesai dijalankan dan memanggil fungsiset
masing-masing. Hal ini mencegah terjadinya beberapa pembaruan ulang selama satu event. Dalam kasus yang jarang terjadi di mana Anda perlu memaksa React untuk memperbarui tampilan lebih awal, misalnya untuk mengakses DOM, Anda dapat menggunakanflushSync
. -
Memanggil fungsi
set
selama rendering hanya diperbolehkan dari dalam komponen yang sedang di-render saat ini. React akan membuang hasilnya dan segera mencoba me-render kembali dengan state yang baru. Pola ini jarang dibutuhkan, tetapi bisa digunakan untuk menyimpan informasi dari render sebelumnya. See an example below. -
Pada mode ketat, React akan memanggil fungsi pembaruan Anda dua kali untuk membantu Anda menemukan kejadian yang tidak diharapkan. Ini hanya terjadi di lingkungan pengembangan dan tidak memengaruhi produksi. Jika fungsi pembaruan Anda murni (seperti seharusnya), ini tidak akan memengaruhi perilakunya. Hasil dari salah satu panggilan akan diabaikan.
Penggunaan
Menambahkan state pada sebuah komponen
Memanggil useState
di tingkat atas komponen Anda untuk mendeklarasikan satu atau lebih variabel state.
import { useState } from 'react';
function MyComponent() {
const [age, setAge] = useState(42);
const [name, setName] = useState('Taylor');
// ...
Konvensi dalam menamai variabel state adalah menggunakan pola [something, setSomething]
dengan array destructuring.
useState
mengembalikan sebuah senarai yang memiliki dua nilai:
- state saat ini dari variabel state ini, awalnya diatur ke state awal yang Anda berikan.
- fungsi
set
yang memungkinkan Anda mengubahnya ke nilai lain sebagai respons terhadap suatu interaksi.
Untuk memperbarui tampilan layar, panggil fungsi set
dengan state berikutnya:
function handleClick() {
setName('Robin');
}
React akan menyimpan state berikutnya, me-render komponen Anda kembali dengan nilai baru, dan memperbarui antarmuka pengguna.
Example 1 of 4: Penghitung (angka)
Dalam contoh ini, variabel state count
menyimpan sebuah angka. Dengan mengklik tombol, angka tersebut akan bertambah.
import { useState } from 'react'; export default function Counter() { const [count, setCount] = useState(0); function handleClick() { setCount(count + 1); } return ( <button onClick={handleClick}> You pressed me {count} times </button> ); }
Memperbarui state berdasarkan state sebelumnya
Misalkan age
adalah 42
. Lalu handler ini memanggil setAge(age + 1)
sebanyak tiga kali:
function handleClick() {
setAge(age + 1); // setAge(42 + 1)
setAge(age + 1); // setAge(42 + 1)
setAge(age + 1); // setAge(42 + 1)
}
Namun, setelah satu kali klik, age
hanya akan menjadi 43
daripada 45
! Hal ini terjadi karena memanggil fungsi set
tidak memperbarui variabel state age
pada kode yang sudah dieksekusi. Oleh karena itu, setiap panggilan setAge(age + 1)
menjadi setAge(43)
.
Untuk memecahkan masalah ini, Anda dapat mengoper sebuah fungsi pembaruan (updater function) pada setAge
daripada mengoper state berikutnya:
function handleClick() {
setAge(a => a + 1); // setAge(42 => 43)
setAge(a => a + 1); // setAge(43 => 44)
setAge(a => a + 1); // setAge(44 => 45)
}
Di sini, a => a + 1
adalah fungsi pembaruan Anda. Fungsi ini mengambil state tertunda dan mengkalkulasi state selanjutnya darinya.
React menempatkan fungsi pembaruan Anda dalam sebuah antrian. Selanjutnya, selama render berikutnya, React akan memanggil fungsi-fungsi tersebut dalam urutan yang sama:
a => a + 1
akan menerima42
sebagai state yang tertunda dan mengembalikan43
sebagai state berikutnya.a => a + 1
akan menerima43
sebagai state yang tertunda dan mengembalikan44
sebagai state berikutnya.a => a + 1
akan menerima44
sebagai state yang tertunda dan mengembalikan45
sebagai state berikutnya.
Karena tidak ada pembaruan antrian lainnya, maka React akan menyimpan 45
sebagai state saat ini.
Secara konvensi, umumnya disepakati untuk memberi nama argumen state tertunda dengan huruf pertama dari nama variabel state, seperti a
untuk age
. Namun, Anda juga dapat memberinya nama seperti prevAge
atau sesuatu yang menurut Anda lebih jelas.
React mungkin akan memanggil pembaruan Anda dua kali pada saat pengembangan untuk memeriksa apakah mereka murni.
Deep Dive
Anda mungkin mendengar rekomendasi untuk selalu menulis kode seperti setAge(a => a + 1)
jika state yang Anda atur dikalkulasi dari state sebelumnya. Tidak ada masalah dengan itu, tetapi juga tidak selalu diperlukan.
Pada kebanyakan kasus, tidak ada perbedaan antara kedua pendekatan tersebut. React selalu memastikan bahwa untuk tindakan pengguna yang disengaja, seperti klik, variabel state age
akan diperbarui sebelum klik berikutnya. Ini berarti tidak ada risiko klik handler melihat age
yang “usang” di awal event handler.
Namun, jika Anda melakukan beberapa pembaruan dalam satu event, fungsi pembaruan dapat membantu. Mereka juga membantu jika mengakses variabel state itu sendiri merepotkan (Anda mungkin mengalaminya saat mengoptimalkan render ulang).
Jika Anda lebih suka konsistensi daripada sintaks yang sedikit lebih panjang, masuk akal untuk selalu menulis fungsi pembaruan jika state yang Anda atur dikalkulasi dari state sebelumnya. Jika dihitung dari state sebelumnya dari beberapa variabel state yang lain, Anda mungkin ingin menggabungkannya menjadi satu objek dan menggunakan reducer.
Example 1 of 2: Mengoper fungsi pembaruan
Contoh ini menggunakan fungsi pembaruan, sehingga tombol “+3” berfungsi.
import { useState } from 'react'; export default function Counter() { const [age, setAge] = useState(42); function increment() { setAge(a => a + 1); } return ( <> <h1>Your age: {age}</h1> <button onClick={() => { increment(); increment(); increment(); }}>+3</button> <button onClick={() => { increment(); }}>+1</button> </> ); }
Memperbarui objek dan senarai di dalam state
Anda dapat menempatkan objek dan senarai ke dalam state. Di React, state dianggap sebagai sesuatu yang hanya bisa dibaca, sehingga Anda harus menggantinya (replace) daripada mutasi (mutate) objek yang sudah ada. Misalnya, jika Anda memiliki objek form
di dalam state, jangan mutasi secara langsung:
// 🚩 Don't mutate an object in state like this:
form.firstName = 'Taylor';
Seharusnya, gantikan seluruh objek dengan membuat objek baru:
// ✅ Replace state with a new object
setForm({
...form,
firstName: 'Taylor'
});
Baca memperbarui objek pada state dan memperbarui senarai pada *state untuk belajar lebih lanjut.
Example 1 of 4: Form (objek)
Pada contoh ini, variabel state form
menampung sebuah objek. Setiap masukan memiliki pengendali perubahan yang memanggil setForm
dengan state berikutnya dari keseluruhan form. Spead syntax { ...form }
memastikan bahwa objek state diganti daripada dimutasi (mutated).
import { useState } from 'react'; export default function Form() { const [form, setForm] = useState({ firstName: 'Barbara', lastName: 'Hepworth', email: 'bhepworth@sculpture.com', }); return ( <> <label> First name: <input value={form.firstName} onChange={e => { setForm({ ...form, firstName: e.target.value }); }} /> </label> <label> Last name: <input value={form.lastName} onChange={e => { setForm({ ...form, lastName: e.target.value }); }} /> </label> <label> Email: <input value={form.email} onChange={e => { setForm({ ...form, email: e.target.value }); }} /> </label> <p> {form.firstName}{' '} {form.lastName}{' '} ({form.email}) </p> </> ); }
Menghindari membuat ulang state awal
React menyimpan state awal sekali dan mengabaikannya pada render berikutnya.
function TodoList() {
const [todos, setTodos] = useState(createInitialTodos());
// ...
Meskipun hasil dari createInitialTodos()
hanya digunakan untuk render awal, Anda tetap memanggil fungsi ini pada setiap render. Hal ini dapat menjadi pemborosan jika membuat senarai yang besar atau melakukan kalkulasi yang mahal
Untuk mengatasi hal tersebut, kamu dapat mengopernya sebagai fungsi initializer ke useState
sebagai gantinya:
function TodoList() {
const [todos, setTodos] = useState(createInitialTodos);
// ...
Perhatikan bahwa Anda mengoper createInitialTodos
, yang merupakan fungsi itu sendiri dan bukan createInitialTodos()
, yang merupakan hasil dari pemanggilannya. Jika Anda mengoper sebuah fungsi ke useState
, React hanya akan memanggilnya selama inisialisasi.
React dapat memanggil inisialisator Anda dua kali pada saat pengembangan untuk memeriksa apakah mereka murni.
Example 1 of 2: Mengoper fungsi inisialisasi
Contoh ini mengoper sebuah fungsi inisialisasi, sehingga fungsi createInitialTodos
hanya berjalan ketika inisalisasi. Ini tidak berjalan ketika komponen di-render ulang, seperti ketika Anda mengetikkan masukan.
import { useState } from 'react'; function createInitialTodos() { const initialTodos = []; for (let i = 0; i < 50; i++) { initialTodos.push({ id: i, text: 'Item ' + (i + 1) }); } return initialTodos; } export default function TodoList() { const [todos, setTodos] = useState(createInitialTodos); const [text, setText] = useState(''); return ( <> <input value={text} onChange={e => setText(e.target.value)} /> <button onClick={() => { setText(''); setTodos([{ id: todos.length, text: text }, ...todos]); }}>Add</button> <ul> {todos.map(item => ( <li key={item.id}> {item.text} </li> ))} </ul> </> ); }
Menyetel ulang state menggunakan kunci (key)
Anda sering melihat atribut key
saat me-render daftar. Namun, atribut ini juga memiliki tujuan lain.
Anda dapat menyetel ulang state komponen dengan memberikan key
yang berbeda pada komponen. Pada contoh ini, tombol Reset mengubah variabel state version
, yang kami oper sebagai key
pada Form
. Ketika key
berubah, React membuat ulang komponen Form
(dan semua komponen anaknya) dari awal, sehingga state-nya disetel ulang.
Baca menjaga dan menyetel ulang state untuk mempelajari lebih lanjut.
import { useState } from 'react'; export default function App() { const [version, setVersion] = useState(0); function handleReset() { setVersion(version + 1); } return ( <> <button onClick={handleReset}>Reset</button> <Form key={version} /> </> ); } function Form() { const [name, setName] = useState('Taylor'); return ( <> <input value={name} onChange={e => setName(e.target.value)} /> <p>Hello, {name}.</p> </> ); }
Menyimpan informasi dari render sebelumnya
Biasanya, Anda akan memperbarui state pada event handler. Namun, dalam kasus yang jarang terjadi, Anda mungkin ingin menyesuaikan state sebagai respons terhadap rendering — misalnya, Anda mungkin ingin mengubah variabel state ketika prop berubah.
Dalam kebanyakan kasus, Anda tidak memerlukannya:
- Jika nilai yang Anda butuhkan dapat dikomputasi sepenuhnya dari props saat ini atau state lain, hapus state yang redundan tersebut. Jika Anda khawatir tentang komputasi ulang yang terlalu sering,
useMemo
Hook dapat membantu. - Jika Anda ingin menyetel ulang seluruh state komponen, berikan
key
yang berbeda pada komponen Anda. - Jika Anda bisa, perbarui semua state yang relevan pada event handler.
Dalam kasus yang jarang terjadi bahwa tidak satu pun dari yang disebutkan di atas berlaku, ada pola yang dapat Anda gunakan untuk memperbarui state berdasarkan nilai-nilai yang telah di-render, dengan memanggil fungsi set
ketika komponen Anda sedang di-render..
Berikut contohnya. Komponen CountLabel
ini menampilkan prop count
yang dioper kepadanya::
export default function CountLabel({ count }) {
return <h1>{count}</h1>
}
Misalkan Anda ingin menunjukan apakah penghitung telah meningkat atau menurun sejak perubahan terakhir. Prop count
tidak memberi tahu hal ini — Anda perlu menelusuri dari nilai sebelumnya. Tambahkan variabel state prevCount
untuk menelusurinya. Tambahkan variabel state lain bernama trend
untuk menampung apakah hitungan telah meningkat atau menurun. Bandingkan prevCount
dengan count
, dan jika tidak sama, perbarui prevCount
dan trend
. Sekarang Anda dapat menampilkan prop hitungan saat ini dan bagaimana ia telah berubah sejak render terakhir.
import { useState } from 'react'; export default function CountLabel({ count }) { const [prevCount, setPrevCount] = useState(count); const [trend, setTrend] = useState(null); if (prevCount !== count) { setPrevCount(count); setTrend(count > prevCount ? 'increasing' : 'decreasing'); } return ( <> <h1>{count}</h1> {trend && <p>The count is {trend}</p>} </> ); }
Perhatikan bahwa jika Anda memanggil fungsi set
saat rendering, itu harus berada dalam kondisi seperti prevCount !== count
, dan harus ada pemanggilan seperti setPrevCount(count)
di dalam kondisi tersebut. Jika tidak, komponen Anda akan di-render dalam perulangan hingga terjadi crash. Selain itu, Anda hanya dapat memperbarui state dari komponen yang sedang di-render seperti ini. Memanggil fungsi set
dari komponen lain selama rendering adalah kesalahan. Terakhir, pemanggilan set
Anda harus memperbarui state tanpa mutasi — ini bukan berarti Anda dapat melanggar aturan fungsi murni.
Pola ini bisa sulit dipahami dan biasanya lebih baik untuk dihindari. Namun, ini lebih baik daripada memperbarui state dalam efek. Ketika Anda memanggil fungsi set
selama render, React akan me-render ulang komponen tersebut sesaat setelah komponen Anda keluar dengan pernyataan return
, dan sebelum me-render anak-anak. Dengan begitu, anak-anak tidak perlu me-render dua kali. Sisa fungsi komponen Anda tetap akan dieksekusi (dan hasilnya akan dibuang). Jika kondisi Anda berada di bawah semua panggilan Hook, Anda dapat menambahkan return
lebih awal untuk memulai ulang render sebelumnya.
Pemecahan masalah
Saya sudah memperbarui state, tetapi saat saya mencetak log nilainya masih yang lama
Memanggil fungsi set
tidak mengubah state pada kode yang sedang berjalan:
function handleClick() {
console.log(count); // 0
setCount(count + 1); // Request a re-render with 1
console.log(count); // Still 0!
setTimeout(() => {
console.log(count); // Also 0!
}, 5000);
}
Ini terjadi karena state berperilaku seperti snapshot. Memperbarui state membutuhkan render ulang dengan nilai state baru, tetapi tidak memengaruhi variabel JavaScript count
pada event handler yang sedang berjalan.
Jika Anda perlu menggunakan state selanjutnya, Anda dapat menyimpannya dalam variabel sebelum mengopernya pada fungsi set
:
const nextCount = count + 1;
setCount(nextCount);
console.log(count); // 0
console.log(nextCount); // 1
Saya telah memperbarui state, tetapi tidak ada perbaruan pada layar
React akan mengabaikan pembaruan Anda jika state berikutnya sama dengan state sebelumnya, yang ditentukan oleh perbandingan Object.is
. Ini biasanya terjadi ketika Anda mengubah objek atau senarai di dalam state secara langsung:
obj.x = 10; // 🚩 Wrong: mutating existing object
setObj(obj); // 🚩 Doesn't do anything
Anda mengubah objek obj
yang ada dan mengirimkannya kembali ke setObj
, sehingga React mengabaikan pembaruan tersebut. Untuk memperbaikinya, pastikan Anda selalu mengganti objek dan senarai di dalam state daripada memutasi mereka:
// ✅ Correct: creating a new object
setObj({
...obj,
x: 10
});
Saya mendapatkan galat: “Too many re-renders”
Anda mungkin mendapatkan galat yang mengatakan: *Too many re-renders*. React membatasi jumlah render untuk mencegah pengulangan tak terbatas.
Biasanya ini berarti bahwa Anda secara tidak kondisional mengatur state selama render, sehingga komponen Anda masuk ke dalam perulangan: render, set state (yang menyebabkan render), render, set state (yang menyebabkan render), dan seterusnya. Sangat sering, ini disebabkan oleh kesalahan dalam menentukan event handler:
// 🚩 Wrong: calls the handler during render
return <button onClick={handleClick()}>Click me</button>
// ✅ Correct: passes down the event handler
return <button onClick={handleClick}>Click me</button>
// ✅ Correct: passes down an inline function
return <button onClick={(e) => handleClick(e)}>Click me</button>
Jika Anda tidak dapat menemukan penyebab kesalahan ini, klik pada panah di sebelah galat pada konsol dan lihat melalui tumpukan JavaScript untuk menemukan panggilan fungsi set
yang bertanggung jawab atas kesalahan tersebut.
Fungsi inisialisasi atau pembaruan saya berjalan dua kali
Pada Strict Mode, React akan memanggil beberapa fungsi Anda sebanyak dua kali alih-alih hanya satu kali:
function TodoList() {
// This component function will run twice for every render.
const [todos, setTodos] = useState(() => {
// This initializer function will run twice during initialization.
return createTodos();
});
function handleClick() {
setTodos(prevTodos => {
// This updater function will run twice for every click.
return [...prevTodos, createTodo()];
});
}
// ...
Ini sesuatu yang sudah diperkirakan dan seharusnya tidak merusak kode Anda.
Perikalu ini hanya terjadi pada saat pengembangan dan membantu Anda menjaga komponen bersifat murni. React menggunakan hasil dari salah satu pangiglan, dan mengabaikan hasil panggilan yang lain. Selama fungsi komponen, insialisasi, dan pembaruan Anda murni, ini tidak akan mempengaruhi logika Anda. Namun, jika secara tidak sengaja terdapat fungsi tidak murni (impure), ini akan membantu Anda untuk mengetahui kesalahan.
Sebagai contoh, fungsi pembaruan tidak murni ini mengubah sebuah senarai di dalam state:
setTodos(prevTodos => {
// 🚩 Mistake: mutating state
prevTodos.push(createTodo());
});
Karena React memanggil fungsi pembaruan dua kali, Anda akan melihat todo ditambahkan dua kali, sehingga Anda akan tahu bahwa ada kesalahan. Dalam contoh ini, Anda dapat memperbaiki kesalahan dengan mengganti senarai tersebut daripada memutasi:
setTodos(prevTodos => {
// ✅ Correct: replacing with new state
return [...prevTodos, createTodo()];
});
Apabila fungsi pembaruan ini murni, memanggilnya beberapa kali tidak membuat perbedaan perilaku. Inilah mengapa React memanggilnya dua kali untuk membantu Anda menemukan kesalahan. Hanya fungsi komponen, inisialisasi, dan pembaruan yang perlu bersifat murni. Event handler tidak perlu murni, sehingga React tidak akan pernah memanggil event handler Anda dua kali.
Baca menjaga komponen murni untuk belajar lebih lanjut.
Saya mencoba mengatur state ke sebuah fungsi, namun malah dipanggil
Anda tidak dapat mengoper sebuah fungsi ke dalam state seperti ini.:
const [fn, setFn] = useState(someFunction);
function handleClick() {
setFn(someOtherFunction);
}
Karena Anda mengoper sebuah fungsi, React menganggap bahwa someFunction
adalah fungsi inisialisasi, dan bahwa someOtherFunction
adalah fungsi pembaruan, sehingga mencoba memanggil mereka dan menyimpan hasilnya. Untuk benar-benar menyimpan fungsi, Anda harus menambahkan () =>
sebelum keduanya. Kemudian React akan menyimpan fungsi yang Anda oper.
const [fn, setFn] = useState(() => someFunction);
function handleClick() {
setFn(() => someOtherFunction);
}