استفاده از هوک state
هوکها پس از انتشار نسخهی 16.8 به ریاکت اضافه شدهاند. آنها به شما اجازه میدهند که از state و دیگر قابلیت های ریاکت بدون نوشتن کلاس استفاده کنید.
در صفحهی معرفی از این مثال برای معرفی هوکها استفاده شد:
import React, { useState } from 'react';
function Example() {
// "count" جدید به نام state تعریف کردن یک متغیر const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
ما با مقایسه این کد با یک مثال مشابه که بر پایه کلاس نوشته شدهاست، یادگیری هوکها را شروع میکنیم.
مثال کلاس مشابه
اگر قبلا از کلاسها در ریاکت استفاده کردهباشید، این کد باید برای شما آشنا باشد:
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
این state در شروع به عنوان { count: 0 }
تعریف شدهاست، و ما مقدار state.count
را وقتی که کاربر روی دکمه کلیک میکند با استفاده از this.setState()
افزایش میدهیم. ما همواره از این الگو در تمام صفحه استفاده میکنیم.
توجه:
شاید برای شما این سوال پیش بیاید که چرا ما استفاده از یک شمارنده(counter) را به استفاده از یک مثال واقعیتر ترجیح دادهایم. چون این به ما کمک میکند تا روی API تمرکز کنیم در حالی که هنوز در اول راه یادگیری هوکها هستیم.
هوکها و کامپوننتهای تابعی
بهعنوان یک یادآوری، کامپوننتهای تابعی در ریاکت به شکل زیر هستند:
const Example = (props) => {
// شما میتوانید از هوکها در اینجا استفاده کنید!
return <div />;
}
یا به این شکل:
function Example(props) {
// شما میتوانید از هوکها در اینجا استفاده کنید!
return <div />;
}
شاید شما در گذشته این کامپوننتها را با نام “کامپوننتهای بدون state” میشناختید. ما حالا قابلیتی را معرفی میکنیم که با استفاده از آن میتوانید از state ریاکت در این نوع کامپوننتها استفاده کنید، بنابراین ما این نوع کامپوننت ها را “کامپوننت تابعی” مینامیم.
شما نمی توانید از هوکها در کلاسها استفاده کنید. ولی با استفاده از آنها دیگر احتیاجی به نوشتن کلاس نخواهید داشت.
هوک چیست؟
مثال جدید خود را با import کردن هوک useState
از ریاکت شروع میکنیم:
import React, { useState } from 'react';
function Example() {
// ...
}
هوک چیست؟ هوک یک تابع ویژه است که به شما اجازه میدهد از امکانات ریاکت استفاده کنید. برای مثال، هوک useState
به شما این امکان را میدهد که از state در کامپوننتهای تابعی استفاده کنید. هوکهای دیگری هم وجود دارند که به یادگیری آنها در آموزشهای بعدی میپردازیم.
چه زمانی میتوانم از هوک استفاده کنم؟ اگر شما یک کامپوننت تابعی بنویسید و متوجه شوید که نیاز به استفاده از state در آن دارید، در گذشته و قبل از معرفی هوکها مجبور بودید که کامپوننت خود را به کلاس کامپوننت تبدیل کنید. حالا با معرفی هوکها میتوانید هر وقت که بخواهید در کامپوننتهای تابعی خود از state استفاده کنید. ما در ادامه این کار را انجام خواهیم داد!
توجه:
چند قانون ویژه درباره این که چه جاهایی از کامپوننت میتوانید یا نمیتوانید از هوکها استفاده کنید وجود دارد. که باید آنها را در قوانین هوکها یاد بگیریم.
تعریف کردین متغیر state
حلا قصد داریم که مقدار اولیه count
را در درون state، عدد 0
تعریف کنیم. بدین منظور، در سازندهی کلاس this.state
را معادل {count: 0}
تعریف میکنیم.
class Example extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 }; }
در یک کامپوننت تابعی، کلید واژهی this
وجود ندارد، پس ما نمی توانیم مقدار this.state
را بخوانیم و یا مقداری را به آن اختصاص دهیم. در عوض، ما میتوانیم از هوک useState
بهطور مستقیم در کامپوننت خود استفاده کنیم:
import React, { useState } from 'react';
function Example() {
// "count" جدید به نام state تعریف کردن یک متغیر const [count, setCount] = useState(0);
با استفاده از useState
چه کارهایی میتوان انجام داد؟ هدف کلی آن تعریف کردن “متغیر state” است. ما در اینجا متغیری به نام count
داریم ولی میتوانیم نام دلخواه، مثل banana
هم برای آن انتخاب کنیم. این یک راه برای “حفظ” برخی مقادیر میان تماسهای تابعی است — useState
یک راه جدید است که دقیقا امکانات مشابه this.state
در کلاس را فراهم میکند. به طور معمول، مقادیر موجود در تابع پس از بسته شدن تابع از بین میروند ولی متغیر state پس از بسته شدن تابع هم توسط ریاکت حفظ میشود.
چه چیزی را به عنوان آرگومان به useState
پاس میدهیم؟ تنها آرگومانی که به هوک useState()
میدهیم مقدار اولیهی state است. بر خلاف کاری که در کلاس ها انجام میدهیم، state حتما نباید یک object باشد. اگر ما به Number یا String احتیاج داریم می توانیم state را به عنوان Number یا String تعریف کنیم. در مثال، ما فقط به یک عدد احتیاج داریم که بفهمیم کاربر چند بار کلیک کردهاست، پس 0
را به عنوان مقدار اولیهی state خود به useState پاس میدهیم. (اگر ما بخواهیم دو مقدار متفاوت را در state ذخیره کنیم، باید دوبار از useState()
استفاده کنیم.)
useState
چه چیزی را بر میگرداند؟ این هوک یک جفت آیتم را بر میگرداند: یک state به نام count و یک تابع برای بهروزرسانی مقدار آن. به این دلیل است که ما آن را به صورت const [count, setCount] = useState()
نوشتهایم. این مقادیر مشابه this.state.count
و this.setState
در کلاس کامپوننت هستند، اگر شما با این نوع syntax آشنایی ندارید، ما در پایین این صفحه به آن میپردازیم.
حالا که متوجه کاربرد هوک useState
شدیم، باید مثال ما را بهتر متوجه شوید:
import React, { useState } from 'react';
function Example() {
// "count" جدید به نام state تعریف کردن یک متغیر const [count, setCount] = useState(0);
ما یک متغیر state به نام count
تعریف کردهایم، و مقدار آن را برابر 0
قرار دادهایم. ریاکت مقدار این state را میان رندر کردن دوبارهی کامپوننت حفظ میکند، و جدیدترین مقدار آن را برای تابع فراهم میکند. اگر ما بخواهم مقدار count
را بهروزرسانی کنیم، میتوانیم از setCount
استفاده کنیم.
توجه:
شاید براتون این سوال پیش بیاد: چرا از اسم
useState
استفاده کردیم و به جای آن از اسمcreateState
استفاده نکردیم؟استفاده از نام “Create” بسیار دقیق نخواهد بود چون یک state فقط در زمان اولین رندر یک کامپوننت ساخته میشود. در هنگام رندر های بعدی،
useState
فقط مقدار state را به ما میدهد. در غیر این صورت اگر قرار بود در هر رندر یک state با همان مقدار ساخته شود که دیگر state نبودند! یک دلیل دیگر هم وجود دارد همیشه نام هوکها باuse
شروع میشود.دلیل این را هم میتوانید در قوانین هوکها مطالعه کنید.
خواندن State
وقتی که ما بخواهیم مقدار شمارش فعلی را نمایش دهیم، از this.state.count
میخوانیم:
<p>You clicked {this.state.count} times</p>
در تابع، ما میتوانیم به طور مستقیم از count
استفاده کنیم:
<p>You clicked {count} times</p>
بهروزرسانی State
در کلاس، ما باید با استفاده از this.setState()
مقدار state count
را بهروزرسانی کنیم:
<button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me
</button>
در تابع، ما از قبل setCount
و count
به عنوان یک متغیر تعریف کردایم پس دیگر احتیاج به استفاده از کلید واژهی this
نداریم:
<button onClick={() => setCount(count + 1)}> Click me
</button>
خلاصه
حالا بیاید خلاصه چیزهایی که یادگرفتهایم را خط به خط برسی کنیم و بفهمیم چه چیزهایی یاد گرفتهایم.
1: import React, { useState } from 'react'; 2:
3: function Example() {
4: const [count, setCount] = useState(0); 5:
6: return (
7: <div>
8: <p>You clicked {count} times</p>
9: <button onClick={() => setCount(count + 1)}>10: Click me
11: </button>
12: </div>
13: );
14: }
- خط ۱: ما هوک
useState
را از ریاکت import کردیم. که به شما اجازهی استفاده از state را در تابع میدهد. - خط ۴: در تابع کامپوننت
Example
، ما با استفاده از هوکuseState
یک متغیر state تعریف کردهایم. که بر اساس اسمهایی که به آن میدهیم یک جفت آیتم را بر میگرداند. ما اسم متغیر خود را راcount
گذاشتیم چون مقدار تعداد کلیکهایی که روی دکمه میکنیم را در خود نگه میدارد. ما مقدار اولیه آن را بهوسیلهی پاس دادن0
به عنوان آرگومان بهuseState
برابر0
قرار دادهایم. مقدار دومی کهuseState
برمیگرداند یک تابع است. این تابع به شما اجازه میدهد که مقدارcount
را بهروزرسانی کنید پس ما اسم آن راsetCount
میگذاریم. - خط ۹: وقتی که کاربر روی دکمه کلیک میکند، ما با استفاده از
setCount
مقدار جدید را به statecount
میدهیم. سپس ریاکت کامپوننتExample
را دوباره رندر میکند، و مقدار جدیدcount
را به آن پاس میدهد.
حجم مطالب ممکن است باری یادگیری در اولین بار زیاد به نظر برسد. ولی عجله نکنید! اگر شما هر کدام از توضیحات را متوجه نشدهاید، مثال بالا را دوباره بخوانید و سعی کنید یک بار دیگر مطالب را از بالا به پایین با دقت بخوانید. ما به شما این قول را میدهیم اگر یکبار دیگر تلاش به خواندن این مطلب بکنید “فراموش میکنید” که state در کلاسها چگونه کار میکند.
نکته: کروشه ([]) چه کاری انجام میدهد؟
شاید متوجه استفاده از کروشه([]) موقع تعریف متغیر state شدهباشید:
const [count, setCount] = useState(0);
اسمهای سمت چپ جزئی از API ریاکت نیستند. و شما میتوانید نام دلخواه برای متغیر استفاده کنید:
const [fruit, setFruit] = useState('banana');
این یک syntax جاوااسکریپت به نام “array destructuring” است. و به این معنی که ما دو متغیر به نامهای fruit
و setFruit
را تعریف کردهایم. تابع useState
دو مقدار را باز میگرداند که به ترتیب به fruit
و setFruit
اختصاص داده میشوند. کد زیر مشابه همین کار را انجام میدهد:
var fruitStateVariable = useState('banana'); // یک جفت آیتم را باز میگرداند
var fruit = fruitStateVariable[0]; // آیتم اول
var setFruit = fruitStateVariable[1]; // آیتم دوم
وقتی که ما توسط useState
یک متغیر state تعریف میکنیم، useState
یک جفت آیتم را بازمیگرداند — یک آرایه با دو آیتم. آیتم اول حاوی مقدار متغیر است، و آیتم دوم یک تابع برای بهروزرسانی مقدار آن است. استفاده از [0]
و [1]
برای دسترسی ممکن است مقداری گمراهکننده باشد چون ما موقع کار با آرایه از آنها استفاده میکنیم برای همین ما به بهجای آن از array destructuring استفاده میکنیم.
توجه:
شاید کنجکاو باشید که بدانید که ریاکت چگونه میفهمد که هر
useState
با کدام کامپوننت مطابقت دارد در صورتی که ما هیچ چیزی مانند کلید واژهیthis
را به ریاکت پاس نمیدهیم. ما به این سوال و سوالات دیگر در بخش پرسش و پاسخ جواب دادهایم.
نکته: استفاده از چندین متغیر state
تعریف کردن متغیر state به عنوان جفت [something, setSomething]
میتواند برای ما مفید باشد چون به ما این امکان را میدهد که از اسامی مختلف برای نام گذاری state ها استفاده کنیم اگر بخواهیم بیشتر از یک state تعریف کینم:
function ExampleWithManyStates() {
// state تعریف کردن چندین!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
در کامپوننت بالا، ما متغیرهای age
، fruit
و todos
را داریم، و میتوانیم هر کدام را جداگانه بهروزرسانی کنیم:
function handleOrangeClick() {
// this.setState({ fruit: 'orange' }) مشابه
setFruit('orange');
}
شما مجبور نیستید متغیرهای state زیادی تعریف کنید. چون متغیرهای state توانایی نگهداری object و array را هم دارد، پس میتوانید مقدارهای مربوط به هم را به عنوان یک گروه تعریف کنید. با این حال، برخلاف this.setState
در کلاس، بهروزرسانی یک متغیر state همیشه به جای ترکیب کردن از جایگزین کردن استفاده میکند.
ما توصیههای بیشتری را دربارهی متغیر state در بخش پرسش و پاسخ فراهم کردهایم.
قدمهای بعدی
در این صفحه ما یکی از هوکها به نام useStae
که توسط ریاکت فراهم شدهاست را یاد گرفتهایم. همچین ما گاهی اوقات از آن به عنوان “State Hook” یاد میکنیم. که به ما این امکان را میدهد که از state در کامپوننت تابعی استفاده کنیم — که این امکان برای اولین بار فراهم شدهاست!
همچنین ما دربارهی هوکها بیشتر یاد گرفتهایم. و فهمیدیم که هوکها توابعی هستند که به ما امکان استفاده از امکانات ریاکت را در کامپوننت تابعی میدهند. نام آنها همیشه با use
شروع میشود، و هوکهای دیگری هم وجود دارند که در آینده با آنها آشنا خواهیم شد.
حالا با یادگیری هوک بعدی: useEffect
ادامه دهید که به شما امکانات مشابه method چرخهی حیات که در کلاس کامپوننت وجود دارد را میدهد.