Mengurus Keadaan Komponen dengan useState
Perkenalkan cangkuk useState, simpan nilai pembilang atau togol dalam keadaan dan cetuskan pemaparan semula dengan memanggil fungsi penetap keadaan.
Mengurus Keadaan Komponen dengan useState ialah pelajaran React Native Academy percuma di CoddyKit. Ini ialah pelajaran 2 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran React Native Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus React Native Academy merangkumi sejumlah 4 pelajaran.
Apakah Keadaan?
Keadaan ialah data yang boleh berubah dari semasa ke semasa dan dimiliki serta diurus secara dalaman oleh sesuatu komponen. Tidak seperti prop (yang datang daripada induk dan bersifat baca sahaja), keadaan dicipta dan dikemas kini oleh komponen itu sendiri. Apabila keadaan berubah, React secara automatik memaparkan semula komponen untuk mencerminkan nilai baharu dalam UI. Contoh keadaan yang lazim termasuk sama ada modal terbuka, teks yang ditaip oleh pengguna, tab yang sedang dipilih atau item yang diperoleh daripada API. Keadaanlah yang menjadikan komponen React interaktif.
import { View, Text, TouchableOpacity } from 'react-native';
import { useState } from 'react';
export default function Counter() {
// Declare state: count starts at 0
const [count, setCount] = useState(0);
return (
<View style={{ padding: 24, alignItems: 'center' }}>
<Text style={{ fontSize: 48, fontWeight: 'bold' }}>{count}</Text>
<TouchableOpacity
onPress={() => setCount(count + 1)}
style={{ marginTop: 16, padding: 12, backgroundColor: '#4f86f7', borderRadius: 8 }}
>
<Text style={{ color: '#fff', fontSize: 18 }}>Increment</Text>
</TouchableOpacity>
</View>
);
}Tandatangan Cangkuk useState
useState ialah Cangkuk React yang anda panggil pada aras teratas fungsi komponen anda. Ia menerima satu argumen — nilai keadaan awal — dan mengembalikan tatasusunan dengan dua elemen: nilai keadaan semasa dan fungsi penetap. Anda menyahstrukturkan kedua-duanya menggunakan penyahstrukturan tatasusunan. Konvensyen penamaan ialah [value, setValue]. Fungsi penetap ialah fungsi yang anda panggil untuk mengemas kini keadaan — jangan ubah pemboleh ubah keadaan secara terus. Setiap pemboleh ubah keadaan adalah berasingan; panggil useState beberapa kali untuk beberapa bahagian keadaan.
import { useState } from 'react';
function MyComponent() {
// Syntax: const [value, setter] = useState(initialValue);
const [count, setCount] = useState(0); // number
const [name, setName] = useState(''); // string
const [isVisible, setIsVisible] = useState(false); // boolean
const [items, setItems] = useState([]); // array
const [user, setUser] = useState(null); // object or null
// Update state by calling the setter:
// setCount(5); ← sets to 5
// setName('Alice'); ← sets to 'Alice'
// setIsVisible(true); ← sets to true
}Kemas Kini Keadaan Mencetuskan Paparan Semula
Apabila anda memanggil penetap keadaan, React menjadualkan paparan semula komponen. Semasa paparan seterusnya, useState mengembalikan nilai baharu. React mengurus perkara ini dengan bijak — ia mengumpulkan beberapa kemas kini keadaan yang berlaku dalam pengendali peristiwa yang sama dan melakukan satu paparan semula sahaja. Perkara penting yang lain: nilai keadaan dalam paparan semasa adalah tidak boleh diubah. Memanggil setCount(count + 1) tidak mengubah count serta-merta dalam pelaksanaan fungsi semasa — nilai baharu muncul dalam kitaran paparan seterusnya.
import { useState } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
export default function Example() {
const [count, setCount] = useState(0);
function handlePress() {
// These do NOT stack: count is still 0 in this render
setCount(count + 1); // schedules count = 1
setCount(count + 1); // also schedules count = 1, not 2!
// To correctly base on previous value, use functional update:
// setCount(prev => prev + 1); // prev = 0, result = 1
// setCount(prev => prev + 1); // prev = 1, result = 2
}
return (
<TouchableOpacity onPress={handlePress}>
<Text>{count}</Text>
</TouchableOpacity>
);
}Kemas Kini Fungsian dengan Keadaan Sebelumnya
Apabila keadaan baharu bergantung pada keadaan sebelumnya, sentiasa gunakan bentuk kemas kini fungsian: setState(prev => prev + 1). React menjamin bahawa prev ialah nilai keadaan yang paling terkini, walaupun beberapa kemas kini dikumpulkan bersama. Ini amat penting apabila menambah nilai pembilang, menogol nilai boolean, atau menambah item pada tatasusunan secara berturutan dengan pantas (contohnya, ketikan butang yang pantas). Bentuk literal objek (setState(state + 1)) boleh menyebabkan pepijat apabila beberapa kemas kini berlaku sebelum komponen dipaparkan semula.
import { useState } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
export default function SafeCounter() {
const [count, setCount] = useState(0);
function increment() {
// Safe: uses previous state, handles batching correctly
setCount(prev => prev + 1);
}
function decrement() {
setCount(prev => Math.max(0, prev - 1)); // min 0
}
function reset() {
setCount(0); // direct value ok when not based on previous
}
return (
<View style={{ alignItems: 'center', gap: 12, padding: 24 }}>
<Text style={{ fontSize: 48 }}>{count}</Text>
<TouchableOpacity onPress={increment}><Text>+</Text></TouchableOpacity>
<TouchableOpacity onPress={decrement}><Text>-</Text></TouchableOpacity>
<TouchableOpacity onPress={reset}><Text>Reset</Text></TouchableOpacity>
</View>
);
}Menogol Keadaan Boolean
Satu corak yang sangat biasa ialah menogol keadaan boolean antara true dan false. Gunakan bentuk kemas kini fungsian bersama operator NOT logik: setIsOpen(prev => !prev). Cara ini lebih kemas berbanding setIsOpen(!isOpen) kerana ia mengendalikan tekanan pantas dengan betul. Kegunaan biasa termasuk memaparkan atau menyembunyikan modal, mengembangkan atau menciutkan bahagian akordion, bertukar antara main dan jeda, atau menogol ikon bintang kegemaran. Boolean mungkin merupakan jenis keadaan komponen yang paling kerap digunakan.
import { useState } from 'react';
import { View, Text, TouchableOpacity, Modal, StyleSheet } from 'react-native';
export default function ToggleModal() {
const [isVisible, setIsVisible] = useState(false);
return (
<View style={styles.container}>
<TouchableOpacity
style={styles.btn}
onPress={() => setIsVisible(prev => !prev)}
>
<Text style={styles.btnText}>Toggle Modal</Text>
</TouchableOpacity>
<Modal visible={isVisible} transparent animationType='fade'>
<View style={styles.overlay}>
<Text style={styles.modalText}>Hello from the modal!</Text>
<TouchableOpacity onPress={() => setIsVisible(false)}>
<Text style={{ color: '#fff', marginTop: 16 }}>Close</Text>
</TouchableOpacity>
</View>
</Modal>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
btn: { padding: 12, backgroundColor: '#4f86f7', borderRadius: 8 },
btnText: { color: '#fff', fontWeight: 'bold' },
overlay: { flex: 1, backgroundColor: 'rgba(0,0,0,0.7)', justifyContent: 'center', alignItems: 'center' },
modalText: { color: '#fff', fontSize: 20, fontWeight: 'bold' },
});Keadaan dengan Rentetan: Medan Teks Terkawal
Mengikat TextInput pada keadaan menghasilkan medan masukan terkawal. Prop value menetapkan teks yang dipaparkan (daripada keadaan), manakala panggilan balik onChangeText mengemas kini keadaan setiap kali pengguna menaip. Dengan cara ini, keadaan menjadi satu-satunya sumber kebenaran bagi nilai medan masukan — anda boleh membaca, mengesahkan atau mengubah teks pada bila-bila masa dengan membaca pemboleh ubah keadaan. Tanpa mengikatnya pada keadaan (tidak terkawal), anda perlu menggunakan ref untuk membaca nilai medan masukan, yang kurang lazim dalam React.
import { useState } from 'react';
import { View, Text, TextInput, StyleSheet } from 'react-native';
export default function SearchBox() {
const [query, setQuery] = useState('');
return (
<View style={styles.container}>
<TextInput
value={query}
onChangeText={setQuery} // same as: (text) => setQuery(text)
placeholder='Search...'
style={styles.input}
/>
<Text style={styles.preview}>
You typed: <Text style={{ fontWeight: 'bold' }}>{query}</Text>
</Text>
<Text style={styles.count}>{query.length} characters</Text>
</View>
);
}
const styles = StyleSheet.create({
container: { padding: 16, gap: 8 },
input: { borderWidth: 1, borderColor: '#ccc', borderRadius: 8, padding: 12, fontSize: 16 },
preview: { fontSize: 14, color: '#555' },
count: { fontSize: 12, color: '#999' },
});Keadaan dengan Tatasusunan: Menambah dan Mengalih Keluar Item
Apabila keadaan ialah tatasusunan, jangan ubahnya secara terus dengan push atau splice. Sebaliknya, cipta tatasusunan baharu yang mengandungi perubahan itu dan hantarkannya kepada penetap. Untuk menambah item: setItems(prev => [...prev, newItem]). Untuk mengalih keluar item: setItems(prev => prev.filter(item => item.id !== id)). Untuk mengemas kini item: setItems(prev => prev.map(item => item.id === id ? {...item, done: true} : item)). Corak tidak boleh ubah ini membolehkan React mengesan perubahan dan menjadualkan paparan semula yang cekap.
import { useState } from 'react';
import { View, Text, TouchableOpacity, TextInput, FlatList } from 'react-native';
export default function TodoList() {
const [todos, setTodos] = useState([]);
const [input, setInput] = useState('');
function addTodo() {
if (!input.trim()) return;
setTodos(prev => [...prev, { id: Date.now().toString(), text: input.trim(), done: false }]);
setInput('');
}
function toggleDone(id) {
setTodos(prev => prev.map(t => t.id === id ? { ...t, done: !t.done } : t));
}
return (
<View style={{ flex: 1, padding: 16 }}>
<TextInput value={input} onChangeText={setInput} placeholder='Add a todo' />
<TouchableOpacity onPress={addTodo}><Text>Add</Text></TouchableOpacity>
<FlatList
data={todos}
keyExtractor={t => t.id}
renderItem={({ item }) => (
<TouchableOpacity onPress={() => toggleDone(item.id)}>
<Text style={{ textDecorationLine: item.done ? 'line-through' : 'none' }}>
{item.text}
</Text>
</TouchableOpacity>
)}
/>
</View>
);
}Keadaan dengan Objek
Bagi bahagian keadaan yang berkaitan, kumpulkannya dalam satu pemboleh ubah keadaan objek. Apabila mengemas kini keadaan objek, kembangkan keadaan sebelumnya untuk mengekalkan medan yang tidak berubah: setState(prev => ({ ...prev, name: 'Alice' })). Cara ini hanya menulis ganti medan name sambil mengekalkan semua medan lain. Sebagai alternatif, setiap medan boleh mempunyai useState tersendiri — tiada satu pendekatan yang sentiasa lebih baik. Gunakan objek apabila medan sentiasa berubah bersama (seperti borang dengan nama, e-mel dan kata laluan); gunakan keadaan berasingan apabila medan berubah secara bebas.
import { useState } from 'react';
import { View, TextInput, Text, StyleSheet } from 'react-native';
export default function ProfileForm() {
const [form, setForm] = useState({
name: '',
email: '',
bio: '',
});
function updateField(field, value) {
setForm(prev => ({ ...prev, [field]: value }));
}
return (
<View style={{ padding: 16, gap: 12 }}>
<TextInput
value={form.name}
onChangeText={v => updateField('name', v)}
placeholder='Name'
style={styles.input}
/>
<TextInput
value={form.email}
onChangeText={v => updateField('email', v)}
placeholder='Email'
style={styles.input}
/>
<Text style={{ color: '#666' }}>Preview: {form.name} — {form.email}</Text>
</View>
);
}
const styles = StyleSheet.create({
input: { borderWidth: 1, borderColor: '#ccc', borderRadius: 8, padding: 12 },
});Keadaan Awal Lewat
Jika pengiraan keadaan awal mahal (membaca daripada AsyncStorage, menghuraikan set data yang besar), hantarkan fungsi kepada useState, bukannya nilai: useState(() => computeExpensiveValue()). React memanggil fungsi pemula ini hanya sekali semasa paparan pertama komponen, bukan pada setiap paparan seterusnya. Ini dipanggil pemulaan lewat. Menghantar pengiraan mahal sebagai nilai biasa (useState(expensiveCompute())) akan menjalankannya pada setiap paparan, lalu menyebabkan kerja yang tidak diperlukan walaupun keadaan awal hanya digunakan sekali.
import { useState } from 'react';
// Without lazy init: computeExpensiveList() runs on EVERY render
const [list, setList] = useState(computeExpensiveList()); // BAD
// With lazy init: function is called ONCE on mount
const [list, setList] = useState(() => computeExpensiveList()); // GOOD
// Real example: JSON.parse is cheap, but still good practice:
const [settings, setSettings] = useState(() => {
const stored = SomeStorage.get('settings');
return stored ? JSON.parse(stored) : { theme: 'light', lang: 'en' };
});Nilai Terbitan berbanding Keadaan Berlebihan
Jangan simpan nilai dalam keadaan jika nilai itu boleh diterbitkan daripada keadaan atau prop sedia ada. Contohnya, jika anda mempunyai senarai tugasan dalam keadaan, jangan simpan completedCount dalam keadaan juga — kirakannya sebagai todos.filter(t => t.done).length semasa paparan. Menyimpan nilai terbitan dalam keadaan boleh menyebabkan pepijat penyegerakan: anda mungkin terlupa mengemas kini satu nilai apabila mengemas kini nilai yang lain. Masukkan ke dalam keadaan hanya perkara yang tidak boleh diterbitkan, tidak boleh dikira semasa paparan, atau yang ditetapkan secara tak segerak (seperti data respons API). Peraturan ini memastikan keadaan kekal minimum dan bebas pepijat.
import { useState } from 'react';
import { Text, View } from 'react-native';
export default function TodoStats() {
const [todos, setTodos] = useState([
{ id: '1', text: 'Buy groceries', done: true },
{ id: '2', text: 'Write code', done: false },
{ id: '3', text: 'Go for a walk', done: true },
]);
// DERIVED: computed from existing state, not stored in state
const total = todos.length;
const completed = todos.filter(t => t.done).length;
const remaining = total - completed;
return (
<View style={{ padding: 16 }}>
<Text>Total: {total}</Text>
<Text>Completed: {completed}</Text>
<Text>Remaining: {remaining}</Text>
</View>
);
}useState berbanding useRef: Bila Tidak Menggunakan Keadaan
Tidak setiap nilai yang berubah dalam komponen perlu berada dalam keadaan. Jika nilai berubah tetapi tidak perlu mencetuskan paparan semula, simpan nilai itu dalam useRef. Contoh biasa termasuk ID pemasa yang dikembalikan oleh setTimeout, penanda yang menjejaki sama ada permintaan rangkaian sedang berjalan, atau nilai prop sebelumnya. Meletakkan nilai-nilai ini dalam keadaan menyebabkan paparan semula yang tidak diperlukan. useRef mengekalkan nilainya merentas paparan semula (seperti keadaan), tetapi mengemas kini nilainya tidak menjadualkan paparan semula. Peraturan utama: jika antara muka pengguna tidak perlu berubah apabila nilai berubah, gunakan useRef.
import { useState, useRef, useEffect } from 'react';
import { Text, TouchableOpacity, View } from 'react-native';
export default function Timer() {
const [elapsed, setElapsed] = useState(0);
const intervalRef = useRef(null); // timer ID in ref — no re-render needed
function start() {
if (intervalRef.current) return; // already running
intervalRef.current = setInterval(() => {
setElapsed(prev => prev + 1); // state — needs re-render to show
}, 1000);
}
function stop() {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
useEffect(() => () => clearInterval(intervalRef.current), []); // cleanup
return (
<View style={{ alignItems: 'center', padding: 24, gap: 16 }}>
<Text style={{ fontSize: 48 }}>{elapsed}s</Text>
<TouchableOpacity onPress={start}><Text>Start</Text></TouchableOpacity>
<TouchableOpacity onPress={stop}><Text>Stop</Text></TouchableOpacity>
</View>
);
}Semakan Pantas
Uji pemahaman anda tentang konsep Pembangunan Mudah Alih React Native daripada pelajaran ini.
Ulang Kaji Pelajaran
Dalam pelajaran ini, anda mempelajari bahawa useState mengisytiharkan pemboleh ubah keadaan dan menyediakan penetap yang mencetuskan paparan semula, kemas kini fungsian menerbitkan keadaan baharu dengan selamat daripada nilai sebelumnya, dan nilai terbitan hendaklah dikira semasa paparan, bukannya disimpan sebagai keadaan berlebihan. Seterusnya, kita akan meneroka cara menaikkan keadaan untuk berkongsi data antara komponen adik-beradik.
Pelajari JavaScript dengan tutor kecerdasan buatan — percuma
Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.
- Kursus
- 30
- Pelajaran
- 120
Soalan Lazim
Adakah pelajaran “Mengurus Keadaan Komponen dengan useState” percuma?
Ya — sebanyak 3 pelajaran dalam laluan pembelajaran React Native Academy, termasuk “Mengurus Keadaan Komponen dengan useState”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus React Native Academy merangkumi sejumlah 4 pelajaran.
Apakah yang akan saya pelajari dalam “Mengurus Keadaan Komponen dengan useState”?
Perkenalkan cangkuk useState, simpan nilai pembilang atau togol dalam keadaan dan cetuskan pemaparan semula dengan memanggil fungsi penetap keadaan. Anda berlatih React Native Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.
Adakah saya memerlukan pengalaman untuk memulakan React Native Academy?
Tiada pengalaman terdahulu diperlukan. Pembelajaran React Native Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 4.
Berapa lamakah pelajaran “Mengurus Keadaan Komponen dengan useState” diambil?
Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.
Bolehkah saya menulis dan menjalankan kod dalam pelajaran React Native Academy ini?
Ya. Setiap pelajaran React Native Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.
Semua pelajaran dalam kursus ini
- Menghantar Data dengan Props
- Mengurus Keadaan Komponen dengan useState
- Menaikkan Keadaan
- Membina Aplikasi Pembilang Interaktif