قلاب useState - راهنمای جامع اطلاعات PlatoBlockchain Intelligence. جستجوی عمودی Ai.

قلاب useState - راهنمای جامع

ایالت چیست؟

قبل از اینکه عمیقاً وارد قلاب useState شویم، ابتدا این اصطلاح را درک می کنیم دولت است.

State اطلاعاتی را در مورد چیزی در یک زمان معین نشان می دهد.

برای مثال، بیایید یک جعبه متن را در نظر بگیریم.

در ابتدا، چیزی در داخل این جعبه متن وجود ندارد، بنابراین وضعیت آن است خالی. فرض کنید شروع به تایپ Hello در داخل آن کرده اید، برای هر بار زدن کلید وضعیت جعبه متن تغییر می کند. ابتدا «H»، سپس «او»، سپس «هل» و به همین ترتیب تا زمانی که به «سلام» تبدیل شود، خواهد بود.

همچنین توجه داشته باشید که هنگام تایپ کردن، مقدار قبلی را از دست نمی دهید. اگر "H" و سپس "e" را فشار دهید، "او" دریافت می کنید و نه فقط "e". به عبارت دیگر، شما می‌توانید حالت را به عنوان حالت در نظر بگیرید حافظه از جعبه متن

نیاز به حالت در یک جزء React.

بیایید این را با کمک یک مثال درک کنیم.

Codesanbox بدون حالت

در اینجا ما یک ClickCounter مؤلفه ای که تعداد دفعات کلیک روی دکمه Increment را نشان می دهد.

ما با استفاده از متغیر محلی "counter" برای نگه داشتن تعداد کلیک ها

هر بار که روی دکمه افزایش کلیک می کنیم، handleClick تابع فراخوانی خواهد شد. این تابع مقدار شمارنده را 1 افزایش می دهد و همچنین مقدار را در کنسول ثبت می کند.

ادامه دهید، روی دکمه Increment در پیش‌نمایش CodeSandbox کلیک کنید.

چیزی نشد؟

خوب به نظر می رسد منطق ما درست است. مقدار ثبت شده در کنسول (CodeSandbox) هر بار که کلیک می کنیم به درستی به روز می شود، اما چرا این به روز رسانی در UI منعکس نمی شود؟

این به دلیل نحوه عملکرد React است.

  • تغییرات در متغیرهای محلی باعث رندر مجدد نمی شود.
  • در طول یک رندر مجدد، یک کامپوننت از ابتدا ایجاد می شود، یعنی تابع یک جزء (در این مثال تابع ClickCounter است) یک بار دیگر اجرا می شود. از آنجایی که متغیرها (به عنوان مثال، شمارنده) محلی برای تابع هستند، مقادیر قبلی آنها از بین می رود.

بنابراین چگونه می توانیم کامپوننت را بین رندرها به خاطر بسپاریم؟

بله، شما درست این را متوجه شدید! ما این کار را با کمک استفاده از ایالت قلاب.

قلاب useState

قلاب useState مکانیسم هایی را برای حفظ حالت و راه اندازی رندر مجدد فراهم می کند.

بیایید به کاربرد آن نگاه کنیم.

import React, { useState } from "react";
const state = useState(initialValue);

// OR

const state = React.useState(initialValue);

قلاب useState آرایه ای را برمی گرداند که شامل دو آیتم است:

  • A متغیر حالت که ارزش خود را در طول رندر مجدد حفظ می کند. مقدار اولیه ارسال شده به useState در اولین رندر به متغیر state اختصاص داده می شود.
  • A عملکرد تنظیم کننده که متغیر حالت را به روز می کند و همچنین رندر مجدد را راه اندازی می کند.
const state = useState(0);
const data = state[0];
const setData = state[1];

با استفاده از ساختارزدایی آرایه ، می توانیم عبارات فوق را به یک دستور واحد تبدیل کنیم، همانطور که در زیر نشان داده شده است:

const [data, setData] = useState(0);

مقدار اولیه ارسال شده به useState فقط در اولین رندر استفاده می شود. برای رندرهای مجدد، نادیده گرفته می شود.

مقابله با useState

اکنون، بیایید مثال پیش‌خوان قبلی را به‌روزرسانی کنیم تا قلاب useState را نیز در بر گیرد.

  • از آنجایی که به مقدار شمارنده بین رندرهای مجدد نیاز داریم، بیایید آن را به حالت تبدیل کنیم.
const [counter, setCounter] = useState(0);
  • فراخوانی setCounter در داخل تابع handleClick.
const handleClick = () => {
  setCounter(counter + 1);
  console.log(`%c Counter:${counter}`, "color:green");
};

تابع setCounter مقدار شمارنده را 1 به روز می کند و یک رندر مجدد را آغاز می کند. هنگامی که تابع کامپوننت در رندر مجدد فراخوانی می شود، متغیر حالتی که توسط useState برگردانده می شود مقدار به روز شده را خواهد داشت.

CodeSandbox را با کد به روز شده امتحان کنید. روی دکمه Increment کلیک کنید و جادوی useState را در عمل ببینید.

Codesanbox با useState

می توانید آن را در یک رندر مجدد، مؤلفه عملکردی تأیید کنید ClickCounter با مشاهده گزارش های کنسول دوباره فراخوانی می شود. گزارش "ClickCounter start" که در ابتدای کامپوننت اضافه شده است در هر رندر ثبت می شود.

اولین رندر

رندر مجدد

عملکرد به روز رسانی

فرض کنید با هر کلیک می خواهیم مقدار شمارنده را 4 عدد افزایش دهیم.

const handleClick = () => {
  setCounter(counter + 1);
    setCounter(counter + 1);
    setCounter(counter + 1);
    setCounter(counter + 1);
    console.log(`%c Counter:${counter}`, "color:green");
    };

فرض کنید مقدار اولیه شمارنده 0 باشد. انتظار دارید پس از کلیک روی دکمه چه چیزی را ببینید؟

بدون عملکرد به روز رسانی

انتظار داشتید که شمارش 4 باشد درست است؟ اما چرا در عوض 1 را می بینید؟

الف) هر رندر با یک حالت مرتبط است. مقدار آن حالت برای تمام طول عمر آن رندر قفل می ماند.

توجه داشته باشید که گزارش داخل تابع handleClick مقدار شمارنده را به صورت 0 چاپ می کند.

مهم نیست که چند بار متد setCounter را فراخوانی کنید، مقدار شمارنده ثابت می ماند.

const handleClick = () => {
  setCounter(counter + 1);
    setCounter(counter + 1);
    setCounter(counter + 1);
    setCounter(counter + 1);
    console.log(`%c Counter:${counter}`, "color:green");
    };
ب) تا زمانی که تمام کدهای داخل یک رویداد کنترل کننده اجرا نشود، React رندر مجدد را راه اندازی نمی کند.

به همین دلیل، هر فراخوانی setCounter یک رندر جداگانه را راه‌اندازی نمی‌کند. در عوض React این توابع تنظیم کننده را در یک صف اضافه می کند. آنها را به ترتیبی که در صف قرار گرفتند اجرا می کند. به روز رسانی هایی که پس از اجرای تمام دستورات در حالت انجام می شود در رندر بعدی منعکس می شود. این صف از به روز رسانی های چندگانه به عنوان شناخته می شود دسته. این اجازه می دهد تا React عملکرد بیشتری داشته باشد.

بنابراین، در اینجا به جای 4 رندر مختلف، یک رندر واحد دریافت می کنیم.

این مثال ساده است و می‌توانید با به‌روزرسانی کد مانند شکل زیر این مشکل را برطرف کنید:

const handleClick = () => {
setCounter(counter + 4);
    console.log(`%c Counter:${counter}`, "color:green");
    };

اما اگر یک مورد استفاده داشته باشید که بخواهید وضعیت را چندین بار قبل از رندر بعدی به روز کنید.

آنجاست که _ به روزرسانی _ عملکرد مفید است.

می‌توانیم مثال قبلی را با تابع updater به صورت زیر تغییر دهیم:

const handleClick = () => {
  setCounter(prevCounter => prevCounter + 1);
    setCounter(prevCounter => prevCounter + 1);
    setCounter(prevCounter => prevCounter + 1);
    setCounter(prevCounter => prevCounter + 1);
    console.log(`%c Counter:${counter}`, "color:green");
    };

اینجا prevCounter ⇒ prevCounter + 1 عملکرد به روز رسانی را نشان می دهد.

همانطور که قبلا توضیح داده شد، این دستورات به روز کننده نیز در صف قرار می گیرند (بچینگ).

تابع به روز رسانی یک حالت معلق/قبلی دریافت می کند که از آن برای محاسبه وضعیت بعدی استفاده می کند.

دسته‌بندی عملکرد به‌روزرسانی

در زیر CodeSandbox با عملکرد به‌روزرسانی اضافه شده است. سعی کنید روی دکمه افزایش کلیک کنید.

سندباکس عملکرد به‌روزرسانی

عملکرد آغازگر

به مثال زیر دقت کنید. در اینجا ما تابع getItems را فراخوانی می کنیم تا مقدار اولیه حالت را بدست آوریم.

import React from "react";
import { useState } from "react";
function ListItems() { 
  const getItems = () => { 
    console.log(`%c getItems called`, "color:hotpink");
    	return Array(50).fill(0); 
    }; 
  const [items, setItems] = useState(getItems()); 
    
    return ( 
    	<div className="card">
        <ul> {items.map((item, index) => 
        	( <li key={index}>Item {index + 1}		</li>))} 
        </ul> <button onClick={() => setItems([...items, 0])}>Add Item</button> 	</div> );
} 
export default ListItems;

این تابع یک آرایه با اندازه 50 ایجاد می کند و آرایه را با صفر پر می کند. به تصویر زیر مراجعه کنید.

آرایه با 50 صفر پر شده است

سپس این موارد روی صفحه نمایش داده می شوند.

به نظر می رسد همه چیز خوب است اما ما اینجا یک مشکل داریم.

با کلیک بر روی این مورد را اضافه کنید دکمه (واقع در بعد از لیست موارد) برای افزودن یک مورد جدید به لیست. گزارش ها را رعایت کنید.

بدون عملکرد اولیه

آیا مشکل را اینجا می بینید؟

هر بار که آیتمی را اضافه می کنید، گزارش "getItems call" به کنسول اضافه می شود. این بدان معنی است که این تابع در هر رندر فراخوانی می شود.

به یاد داشته باشید که useState مقدار اولیه ارسال شده به آن را پس از اولین رندر نادیده می گیرد، اما در اینجا مقدار اولیه همچنان در حال محاسبه مجدد است. اگر آرایه های بزرگ بسازیم یا محاسبات سنگین انجام دهیم، ممکن است گران باشد.

ما می توانیم این موضوع را با عبور حل کنیم getItems به عنوان _ مقداردهی اولیه _ عملکرد.

حالا بیایید یک تغییر کوچک در کد ایجاد کنیم.

const [items, setItems] = useState(getItems);

با عملکرد اولیه

پنجره کنسول را در CodeSandbox ببینید. توجه داشته باشید که لاگ "getItems call" فقط در اولین رندر چاپ می شود. وقتی موارد بعدی اضافه می شوند، این گزارش وجود ندارد.

اگرچه تفاوت ظاهری بین این دو نمونه وجود ندارد، اما از نظر عملکرد متفاوت هستند.

به یاد داشته باشید زمانی که به یک تابع برای حالت اولیه نیاز دارید، همیشه تابع را ارسال کنید یا تابع را در داخل تابع دیگری فراخوانی کنید. هرگز تابع را مستقیماً فراخوانی نکنید.

✅ const [items, setItems] = useState(getItems);
✅ const [items, setItems] = useState(() => getItems());
❌ const [items, setItems] = useState(getItems());

چند قلاب استفاده دولتی می توانم داشته باشم

شما می توانید به تعداد مورد نیاز قلاب useState در داخل یک جزء داشته باشید.

به CodeSandbox مراجعه کنید

قلاب های حالت چند منظوره

مؤلفه زیر دارای سه حالت مختلف است - نام کاربری، رمز عبور، KeMeSignedIn.

سعی کنید مقادیر نام کاربری، keepMeSignedIn را به روز کنید. با کلیک روی دکمه ورود، حالت های به روز شده در کنسول ثبت می شوند.

های لایت

  • useState مکانیزمی را برای راه اندازی رندر مجدد و تداوم وضعیت بین رندرهای مجدد فراهم می کند.
  • هنگامی که نیاز دارید از عملکرد به روز رسانی استفاده کنید:
    • حالت بعدی را بر اساس حالت قبلی محاسبه کنید.
    • قبل از رندر بعدی، چندین به روز رسانی را برای حالت انجام دهید.
  • اگر حالت اولیه از یک تابع به دست می آید - از دستور تابع اولیه استفاده کنید.
  • می‌تواند چندین قلاب useState در داخل یک جزء وجود داشته باشد.

این پست را دوست داشتید؟ آن را با دیگران به اشتراک بگذارید.
در اصل برای وبلاگ شخصی من نوشته شده است - https://gauravsen.com/use-state-hook

تمبر زمان:

بیشتر از Codementor React Fact