📚 بخش ۱۸: آشنایی با useState و مدیریت State در کامپوننتها

۱. مقدمه — چرا useState مهم است؟
در React نسخههای مدرن (خصوصاً از نسخه ۱۶.۸ به بعد)، استفاده از Hooks باعث شد بتوانیم state و امکانات دیگر را به جای Class Component، داخل تابعها هم داشته باشیم.
اولین و مهمترین Hook که همهی توسعهدهندهها با آن شروع میکنند، useState است.
این Hook به ما این امکان را میدهد که داخل یک کامپوننت تابعی (Functional Component) متغیرهایی با قابلیت ذخیرهسازی حالت و پاسخ به تغییراتشان ایجاد کنیم.
۲. تعریف ساده useState
useState یک تابع از کتابخانهی React است که:
- یک متغیر state ایجاد میکند (برای نگهداری داده)
- یک تابع setter برای تغییر دادن آن متغیر برمیگرداند
ساختار کلی:
const [stateValue, setStateValue] = useState(initialValue);
۳. قدم به قدم — چطور استفاده کنیم؟
۱. هوک را از React ایمپورت میکنیم:
import { useState } from 'react';
- در داخل تابع کامپوننت فراخوانی میکنیم:
const [count, setCount] = useState(0);
count→ مقدار فعلیsetCount→ تابعی برای تغییر مقدار0→ مقدار اولیه state
۴. مثال ساده: شمارنده
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<h1>شمارش: {count}</h1>
<button onClick={() => setCount(count + 1)}>افزایش</button>
<button onClick={() => setCount(count - 1)}>کاهش</button>
</div>
);
}
export default Counter;
تحلیل خط به خط
useState(0)→ state اولیه را صفر قرار میدهد.setCount(count + 1)→ تابعی که state را تغییر میدهد.- وقتی state تغییر کند، React همان کامپوننت را دوباره رندر میکند و مقدار
countجدید را نمایش میدهد.
۵. نکات کلیدی در استفاده از useState
- هر بار که
setStateفراخوانی شود:
- مقدار state تغییر میکند.
- کامپوننت مجدد رندر میشود.
- تغییر مستقیم state بدون استفاده از setter کار نمیکند:
count = count + 1; // ⛔ کار اشتباه
- اگر state جدید بر اساس state قبلی محاسبه میشود، از Callback Form استفاده کنید:
setCount(prev => prev + 1);
این روش مطمئن است چون از مقدار قبلی در همان لحظه استفاده میکند، حتی اگر چند بهروزرسانی همزمان باشند.
۶. مثال: فیلد ورودی
function NameInput() {
const [name, setName] = useState('');
return (
<div>
<input
value={name}
onChange={e => setName(e.target.value)}
placeholder="نام خود را وارد کنید"
/>
<p>نام شما: {name}</p>
</div>
);
}
📌 اینجا داریم از useState برای ذخیره رشته ورودی کاربر استفاده میکنیم.
۷. State میتواند هر نوع دادهای باشد
- رشته (string):
const [text, setText] = useState("سلام");
- عدد (number):
const [count, setCount] = useState(0);
- بولین (boolean):
const [isOpen, setIsOpen] = useState(false);
- آرایه (array):
const [items, setItems] = useState([]);
- شیء (object):
const [user, setUser] = useState({ name: '', age: 0 });
۸. نکته مهم — بروزرسانی state های پیچیده
وقتی state یک آبجکت یا آرایه است، باید نسخه جدیدش را بسازیم چون state در React Immutable است.
مثلاً برای تغییر شیء:
setUser(prev => ({ ...prev, name: "علی" }));
برای اضافه کردن آیتم به آرایه:
setItems(prev => [...prev, "آیتم جدید"]);
۹. مثال پیشرفته — مدیریت چند state
function ProfileForm() {
const [name, setName] = useState('');
const [age, setAge] = useState('');
const [skills, setSkills] = useState([]);
const addSkill = skill => {
setSkills(prev => [...prev, skill]);
};
return (
<div>
<input
value={name}
onChange={e => setName(e.target.value)}
placeholder="نام"
/>
<input
type="number"
value={age}
onChange={e => setAge(e.target.value)}
placeholder="سن"
/>
<button onClick={() => addSkill("React")}>افزودن مهارت React</button>
<p>{name} - {age} سال</p>
<ul>
{skills.map((s, i) => <li key={i}>{s}</li>)}
</ul>
</div>
);
}
۱۰. اشتباهات رایج
❌ تغییر مستقیم state
user.name = "جدید"; // 🔴 اشتباه
✅ باید نسخه کپی بسازیم:
setUser(prev => ({ ...prev, name: "جدید" }));
❌ بهروزرسانی پشت سرهم بدون استفاده از prev state
ممکن است مقدار اشتباهی ثبت شود اگر از حالت callback استفاده نکنید.
۱۱. تمرینهای پیشنهادی
۱. Counter با محدودیت: شمارنده بساز که از ۰ پایینتر و از ۱۰ بالاتر نرود.
۲. لیست خرید: ورودی + دکمه اضافه کردن محصول به آرایه موجودی.
۳. تغییر حالت تم صفحه: دکمهای که بین حالت تاریک و روشن سوییچ کند (boolean state).
۱۲. نکات حرفهای
- اگر state شما بسیار پیچیده شد، بهتر است به جای useState از useReducer استفاده کنید.
- برای کامپوننتهایی که زیاد رندر میشوند، مطمئن شوید تغییر state واقعاً لازم است.
- state باید فقط اطلاعاتی را نگه دارد که بر رابط کاربری تأثیر میگذارد.
۱۳. جمعبندی
useStateقلب مدیریت داده در کامپوننتهای تابعی است.- همیشه برای تغییر state از تابع setter استفاده کن.
- state در React immutable است، پس همیشه نسخه جدید بساز.
- نوع دادهی state میتواند هرچیزی باشد: رشته، عدد، بولین، آرایه یا شیء.
- تغییر state باعث رندر مجدد کامپوننت میشود.