مدیریت State با useState در React
در React، State (وضعیت) یک مقدار دینامیک است که هنگام تغییر، باعث بهروزرسانی و رندر مجدد کامپوننت میشود.
📌 قبل از React 16.8، فقط کامپوننتهای کلاسی میتوانستند State داشته باشند.
📌 بعد از نسخه 16.8، با معرفی هوکها (Hooks)، میتوان از useState در کامپوننتهای فانکشنی هم استفاده کرد.
۱. تعریف State با useState
useState یک آرایه دو عنصری برمیگرداند:
1️⃣ مقدار فعلی State
2️⃣ تابعی برای تغییر مقدار State
ساختار کلی useState
✔ مقدار اولیه initialValue مقدار پیشفرض State است.
✔ setState مقدار جدید را تنظیم کرده و کامپوننت را ریرندر میکند.
۲. مثال ساده: شمارنده (Counter)
const 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) مقدار اولیه را ۰ تنظیم میکند.
✅ setCount(count + 1) مقدار count را افزایش داده و باعث ریرندر میشود.
۳. استفاده از مقدار قبلی State
گاهی اوقات باید مقدار جدید را بر اساس مقدار قبلی تنظیم کنیم. در این حالت از کالبک در setState استفاده میکنیم.
مثال: شمارنده با مقدار قبلی
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(prevCount => prevCount + 1)}>
عدد: {count}
</button>
);
};
✔ در این حالت، مقدار قبلی count در prevCount ذخیره شده و مقدار جدید بر اساس آن تنظیم میشود.
۴. مدیریت Stateهای چندگانه
اگر یک کامپوننت چندین State داشته باشد، میتوان از چند useState جداگانه استفاده کرد.
مثال: مدیریت نام و سن کاربر
const [name, setName] = useState("علی");
const [age, setAge] = useState(25);
return (
<div>
<h2>نام: {name}</h2>
<h2>سن: {age}</h2>
<button onClick={() => setAge(age + 1)}>افزایش سن</button>
</div>
);
};
✔ useState("علی") مقدار اولیه name را علی تنظیم میکند.
✔ setAge(age + 1) مقدار age را یک واحد افزایش میدهد.
۵. مدیریت آرایه در State
در آرایهها، باید مقدار جدید را جایگزین کل آرایه قبلی کنیم.
مثال: اضافه کردن آیتم به لیست
const [todos, setTodos] = useState(["خرید", "ورزش"]);
const addTodo = () => {
setTodos([...todos, "مطالعه"]); // اضافه کردن "مطالعه" به لیست
};
return (
<div>
<ul>
{todos.map((todo, index) => (
<li key={index}>{todo}</li>
))}
</ul>
<button onClick={addTodo}>افزودن کار</button>
</div>
);
};
✔ setTodos([...todos, "مطالعه"]) یک کپی از آرایه قبلی ساخته و مقدار جدید را اضافه میکند.
✔ در React، نباید مستقیماً State را تغییر داد (مثل todos.push("مطالعه")).
۶. مدیریت آبجکت در State
در آبجکتها هم باید کپی جدید بسازیم و مقدار جدید را در آن قرار دهیم.
مثال: تغییر مقدار در آبجکت State
const [user, setUser] = useState({ name: "علی", age: 25 });
return (
<div>
<h2>نام: {user.name}</h2>
<h2>سن: {user.age}</h2>
<button onClick={() => setUser({ ...user, age: user.age + 1 })}>
افزایش سن
</button>
</div>
);
};
✔ setUser({ ...user, age: user.age + 1 }) آبجکت جدیدی میسازد و مقدار age را بهروز میکند.
✔ نباید مستقیماً مقدار user.age را تغییر دهیم.
۷. مقداردهی اولیه از تابع
اگر مقدار اولیه محاسباتی و سنگین باشد، بهتر است از تابع در useState استفاده کنیم تا فقط یکبار اجرا شود.
مثال: مقداردهی اولیه با تابع
console.log("محاسبه مقدار اولیه...");
return 10;
};
const Counter = () => {
const [count, setCount] = useState(getInitialCount);
return <h1>{count}</h1>;
};
✔ getInitialCount فقط یکبار هنگام mount اجرا میشود.
✔ اما اگر useState(getInitialCount()) را بنویسیم، تابع در هر رندر اجرا خواهد شد (مطلوب نیست).
جمعبندی و نکات مهم
✅ useState برای مدیریت State در فانکشنال کامپوننتها استفاده میشود.
✅ مقدار اولیه میتواند عدد، رشته، آرایه یا آبجکت باشد.
✅ نباید State را مستقیماً تغییر داد؛ بلکه باید کپی جدید ساخت.
✅ برای استفاده از مقدار قبلی State، میتوان از کالبک در setState استفاده کرد.
✅ مقداردهی اولیه بهتر است با یک تابع انجام شود اگر محاسبات زیادی نیاز دارد.