State: حافظه ی یک کامپوننت
کامپوننتها اغلب نیاز دارند که به خاطر تعاملات، آنچه در صفحه نمایش داده میشود را تغییر دهند. تایپ کردن در فرم باید مقدار ورودی را بهروزرسانی کند، کلیک بر روی “بعدی” در گالری تصاویر باید تصویر نمایش داده شده را تغییر دهد، کلیک بر روی “خرید” باید محصولی را به سبد خرید اضافه کند. کامپوننت ها نیاز به “یادآوری” چیزها دارند: مقدار ورودی فعلی، تصویر فعلی، سبد خرید. در React، این نوع حافظهٔ مختص به جزئیات کامپوننت به عنوان وضعیت شناخته میشود.
You will learn
چگونه متغیر وضعیتی (state) را با استفاده از هوک ها (Hook) اضافه کنیم؟*
useState
چه جفت مقداری (values) گوی (Hook) useState برمیگرداند؟*
چگونه بیش از یک متغیر وضعیتی (state) اضافه کنیم؟*
چرا وضعیت (state) به عنوان محلی (local) نامیده میشود؟*
When a regular variable isn’t enough
اینجا یک کامپوننت است که یک تصویر مجسمه را نمایش میدهد. با کلیک بر روی دکمه “بعدی” باید مجسمهی بعدی را با تغییر دادن مقدار index به 1، سپس 2 و به همین ترتیب نشان دهد. با این حال، این کار نخواهد کرد (میتوانید امتحان کنید!):
(با دقت داخل کد را بخوانید!)
در اینجا، رویداد handleClick یک دستگیره را به نام index بهروز میکند. اما دو مورد مانع از دیدهشدن این تغییر میشوند:
-
Local variables don’t persist between renders. متغیرهای محلی بین رندرها ثابت نمیمانند. وقتی ریاکت این- کامپوننت را بار دیگر رندر میکند، آن را از ابتدا رندر میکند، و هیچ تغییری در متغیرهای محلی را در نظر نمیگیرد.
-
Changes to local variables won’t trigger renders. تغییرات در متغیرهای محلی رندرها را فراخوانی نمیکنند-.ری اکت درک نمیکند که نیاز به دوباره رندر کردن کامپوننت با دادههای جدید دارد. برای بهروزرسانی یک کامپوننت با دادههای جدید، دو مورد نیاز است که اتفاق بیافت
-
Retain دادهها را حفظ کنید تا بین رندرها باقی بمانند.
-
Triggerبه React علامت بزنید تا کامپوننت را با دادههای جدید رندر کند (دوباره رندر کند). گوی (Hook) useState این دو ویژگی را ارائه میدهد:
-
A state variable متغیر وضعیت برای حفظ دادهها بین رندرها.
-
A state setter function تابع تنظیمکننده وضعیت برای بهروزرسانی متغیر و ایجاد علامتی برای React تا کامپوننت را مجدداً رندر کند.
Adding a state variable
برای اضافه کردن متغیرهای استیت این عبارت را در بالای فایل ری اکت خود اضافه کنید:
import useState
import { useState } from 'react';
Then, replace this line:
let index = 0;
with
const [index, setIndex] = useState(0);
index
is a state variable and setIndex
is the setter function.
The
[
and]
syntax here is called array destructuring and it lets you read values from an array. The array returned byuseState
always has exactly two items.
This is how they work together in handleClick
:
function handleClick() { setIndex(index + 1); }
Now clicking the “Next” button switches the current sculpture:
Meet your first Hook
In React, useState
, as well as any other function starting with “use
”, is called a Hook.
تعریف دقیق هوک:
Hooks یا قلاب- توابع خاصی هستند که تنها زمانی در دسترس هستند که ری اکت درحال رندر است! rendering (which we’ll get into in more detail on the next page). They let you “hook into” different React features.
استیت فقط یکی از انواع هوک یا قلاب است. (به ویژگی های اصلی ری اکت چنگ میزند)
Anatomy of useState
When you call useState
, you are telling React that you want this component to remember something:
const [index, setIndex] = useState(0);
In this case, you want React to remember index
.
تنها آرگومان مورد نیاز برای useState، مقدار اولیه متغیر وضعیت شماست. در این مثال، مقدار اولیه اندیس به 0 تنظیم میشود با استفاده از useState(0). هر بار که کامپوننت شما رندر میشود، useState یک آرایه ارائه میدهد که دو مقدار را شامل میشود:
- The state variable (
index
) with the value you stored. متغیر وضعیت (اندیس) با مقدار ذخیره شده. - The state setter function (
setIndex
) which can update the state variable and trigger React to render the component again. تابع تنظیمکننده وضعیت (تنظیماندیس) که میتواند متغیر وضعیت را بهروز کند و باعث میشود React مجدداً کامپوننت را رندر کند. در زیر نحوه عملکرد آن آمده است:
Here’s how that happens in action:
const [index, setIndex] = useState(0);
- Your component renders the first time.
اولین باری که کامپوننت شما رندر میشود. از آنجا که عدد
0
را به عنوان مقدار اولیه برایindex
بهuseState
پاس دادهاید، آن تابع[0، setIndex]
را باز میگرداند. React به یاد میآورد که0
آخرین مقدار وضعیت است. - You update the state.
شما وضعیت را بهروز میکنید. وقتی کاربر بر روی دکمه کلیک میکند،
setIndex(index + 1)
فراخوانی میشود.index
برابر با0
است، بنابراین این به معنایsetIndex(1)
است. این اقدام باعث میشود React به یاد داشته باشد که حالا مقدارindex
برابر با1
است و یک بار دیگر رندر شود. - Your component’s second render.
دومین رندر کامپوننت شما. هنوز React میبیند که شما از
useState(0)
استفاده کردهاید، اما به دلیل اینکه React به یاد دارد که شماindex
را برابر با1
قرار دادهاید، به جای آن[1، setIndex]
را برمیگرداند. - And so on!
Giving a component multiple state variables
شما میتوانید تعداد دلخواهی از متغیرهای وضعیت با انواع مختلف را در یک کامپوننت داشته باشید. این کامپوننت دارای دو متغیر وضعیت است، یک عدد به نام ایندکس
و یک بولین به نام نمایش_بیشتر
که با کلیک بر روی “نمایش جزئیات” تغییر وضعیت مییابد:
showMore
It is a good idea to have multiple state variables if their state is unrelated, like index
and showMore
in this example. But if you find that you often change two state variables together, it might be easier to combine them into one. For example, if you have a form with many fields, it’s more convenient to have a single state variable that holds an object than state variable per field. Read Choosing the State Structure for more tips.
Deep Dive
شاید متوجه شده باشید که فراخوانی useState
هیچ اطلاعاتی درباره کدام متغیر وضعیت به آن ارجاع داده میشود، دریافت نمیکند. هیچ “شناسه”ای که به useState
منتقل شود وجود ندارد، پس چگونه میداند کدام یک از متغیرهای استیت را برگرداند؟ آیا بر اساس یک جادویی مانند تجزیه و تحلیل توابع عمل میکند؟ پاسخ نه است.
بدلاً از آن، برای فعال کردن دستور زبان مختصر آنها، هوکها بر اعتماد به ترتیب فراخوانی پایدار در هر بار رندر کامپوننت یکسان تکیه میکنند. این در عمل به خوبی کار میکند زیرا اگر قانون فوق را رعایت کنید (“تنها در سطح بالایی دستورهای هوک را فراخوانی کنید”)، هوکها همیشه به همان ترتیب فراخوانی میشوند. علاوه بر این، یک افزونه لینتر اکثر اشتباهات را گرفتار میکند.
در داخل، React یک آرایه از زوجهای استیت برای هر کامپوننت نگه میدارد. همچنین شاخص زوج فعلی را که قبل از رندر شدن به 0
تنظیم شده است، حفظ میکند. هر بار که useState
را فراخوانی میکنید، React زوج وضعیت بعدی را به شما ارائه میدهد و شاخص را افزایش میدهد. میتوانید بیشتر در مورد این مکانیزم در React Hooks: Not Magic, Just Arrays. مطالعه کنید.
React Hooks: Not Magic, Just Arrays.
This example doesn’t use React but it gives you an idea of how useState
works internally:
You don’t have to understand it to use React, but you might find this a helpful mental model.
State is isolated and private
استیت محدود به یک نمونه از کامپوننت در صفحه است. به عبارت دیگر، اگر دو بار همان کامپوننت را رندر کنید، هر نسخه دارای استیت کاملاً جداگانهای خواهد بود! تغییر یکی از آنها تأثیری بر روی دیگری نخواهد داشت.
در این مثال، کامپوننت گالری
که قبلاً ارائه شده بود، دو بار با هیچ تغییری در منطق خود رندر میشود. سعی کنید روی دکمههای درون هر یک از گالریها کلیک کنید. توجه داشته باشید که استیت آنها مستقل است:
این ویژگی باعث میشود که وضعیت از متغیرهای معمولی که ممکن است در بالای ماژولتان تعریف کنید، متفاوت باشد. وضعیت به یک فراخوانی خاص تابع یا یک محل خاص در کد مرتبط نیست، بلکه به مکان مشخصی در صفحه مرتبط میشود. شما دو مولفه <گالری />
را رندر کردهاید، بنابراین وضعیت آنها جداگانه ذخیره میشود.
<Gallery />
همچنین توجه کنید که کامپوننت صفحه
هیچ اطلاعاتی در مورد وضعیت گالری
ندارد و حتی نمیداند که وضعیتی دارد یا نه. به عکس از پراپها، وضعیت کاملاً به کامپوننتی که آن را تعریف میکند، خصوصیت دارد. کامپوننت والد نمیتواند آن را تغییر دهد. این به شما امکان میدهد که به هر کامپوننتی وضعیت اضافه یا آن را حذف کنید بدون اینکه بر روی سایر کامپوننتها تأثیر بگذارید.
Unlike props, state is fully private to the component declaring it. اگر میخواستید هر دو گالری وضعیتهای خود را همگام نگه دارند، راه درست در React این است که از کامپوننتهای فرزند وضعیت را حذف کنید و آن را به نزدیکترین والد مشترک آنها اضافه کنید. صفحات بعدی به تمرکز بر روی سازماندهی وضعیت یک کامپوننت تکی اختصاص دارند، اما ما به این موضوع در (/learn/sharing-state-between-components باز خواهیم گشت.
Recap
نکات مهم:
- از یک متغیر وضعیت استفاده کنید وقتی که یک کامپوننت نیاز دارد که بین رندرها به یک برخی از اطلاعات “یادآوری” کند.
- متغیرهای وضعیت با فراخوانی Hook
useState
اعلام میشوند. - Hook ها تابعهای ویژهای هستند که با
use
آغاز میشوند. آنها به شما اجازه میدهند تا به ویژگیهای React مانند وضعیت متصل شوید. - Hook ها ممکن است به شما یادآوری وارداتها کنند: آنها باید بدون شرط فراخوانی شوند. فراخوانی Hook ها، از جمله
useState
، تنها در سطح بالایی یک کامپوننت یا یک Hook دیگر معتبر است. - Hook
useState
یک زوج از مقادیر را برمیگرداند: وضعیت فعلی و تابع برای بهروزرسانی آن. - شما میتوانید بیش از یک متغیر وضعیت داشته باشید. در داخلی، React آنها را بر اساس ترتیبشان همسان میکند.
- وضعیت به کامپوننت اختصاصی است. اگر آن را در دو مکان رندر کنید، هر نسخه وضعیت خودش را خواهد داشت.
Challenge 1 of 4: Complete the gallery
When you press “Next” on the last sculpture, the code crashes. Fix the logic to prevent the crash. You may do this by adding extra logic to event handler or by disabling the button when the action is not possible.
After fixing the crash, add a “Previous” button that shows the previous sculpture. It shouldn’t crash on the first sculpture.