خطاف useState - دليل شامل لـ PlatoBlockchain Data Intelligence. البحث العمودي. عاي.

خطاف useState - دليل شامل

ما هي الدولة؟

قبل أن نتعمق في خطاف useState ، دعونا أولاً نفهم المصطلح الدولة.

تمثل الحالة معلومات حول شيء ما في وقت معين.

على سبيل المثال ، دعنا نفكر في مربع نص.

في البداية ، لا يوجد شيء داخل مربع النص هذا ، لذا فإن حالته هي فارغ. لنفترض أنك بدأت في كتابة مرحبًا بداخله ، فكل ضربة مفتاح ستتغير حالة مربع النص. في البداية ستكون "H" ، ثم "هو" ، ثم "Hel" وهكذا حتى تصبح "Hello".

لاحظ أيضًا أنك أثناء الكتابة ، لن تفقد القيمة السابقة. إذا ضغطت على "H" متبوعًا بـ "e" ، فستحصل على "He" وليس فقط "e". بعبارة أخرى ، يمكنك التفكير في الحالة على أنها ذاكرة من مربع النص.

الحاجة إلى الحالة في مكون React.

دعونا نفهم هذا بمساعدة مثال.

Codesanbox بدون دولة

هنا لدينا ملف انقر فوقعداد المكون الذي يعرض عدد المرات التي تم فيها النقر فوق الزر زيادة.

نحن نستخدم المتغير المحلي "عداد" للحفاظ على عدد النقرات.

في كل مرة نضغط على زر الزيادة ، مقبض سيتم استدعاء الوظيفة. ستعمل هذه الوظيفة على زيادة قيمة العداد بمقدار 1 وكذلك تسجيل القيمة في وحدة التحكم.

انطلق ، انقر فوق الزر Increment في معاينة CodeSandbox.

لم يحدث شيء؟

حسنًا ، يبدو أن منطقنا صحيح. يتم تحديث القيمة المسجلة في وحدة التحكم (CodeSandbox) بشكل صحيح في كل مرة نضغط فيها ، ولكن لماذا لا ينعكس هذا التحديث في واجهة المستخدم؟

إنه بسبب طريقة عمل React.

  • لا تؤدي التغييرات التي يتم إجراؤها على المتغيرات المحلية إلى إعادة التصيير.
  • أثناء إعادة التصيير ، يتم إنشاء مكون من نقطة الصفر ، أي أن وظيفة المكون (في هذا المثال هي وظيفة ClickCounter) يتم تنفيذها مرة أخرى. نظرًا لأن المتغيرات (على سبيل المثال ، عداد) محلية بالنسبة للوظيفة ، يتم فقد قيمها السابقة.

إذن كيف نجعل المكون يتذكر القيم بين عمليات العرض؟

نعم ، لقد فهمت الأمر بشكل صحيح! نقوم بذلك بمساعدة استخدام صنارة صيد.

خطاف useState

يوفر الخطاف useState آليات للحفاظ على الحالة وتشغيل إعادة التصيير.

دعونا نلقي نظرة على استخدامه.

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

// OR

const state = React.useState(initialValue);

يُرجع الخطاف useState مصفوفة تحتوي على عنصرين:

  • A المتغير الحكومي التي تحتفظ بقيمها أثناء إعادة تصيير. يتم تعيين القيمة الأولية التي تم تمريرها إلى useState إلى متغير الحالة أثناء عملية التصيير الأولى.
  • 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 بالرمز المحدث. انقر فوق الزر زيادة وشاهد سحر useState أثناء العمل.

Codesanbox مع useState

يمكنك التحقق من أنه في إعادة التصيير ، المكون الوظيفي انقر فوقعداد يتم استدعاء مرة أخرى من خلال عرض سجلات وحدة التحكم. سيتم تسجيل السجل "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");
    };

ولكن ماذا لو كانت لديك حالة استخدام حيث أردت تحديث الحالة عدة مرات قبل العرض التالي.

هذا هو المكان الذي _ التحديث _ وظيفة مفيدة.

يمكننا إعادة تشكيل المثال السابق باستخدام وظيفة المُحدِث على النحو التالي:

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");
    };

هنا العداد السابق ⇒ العداد السابق + 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 يسمى" إلى وحدة التحكم في كل مرة تقوم فيها بإضافة عنصر. هذا يعني أنه يتم استدعاء هذه الوظيفة في كل تصيير.

تذكر أن useState يتجاهل القيمة الأولية التي تم تمريرها إليها بعد التصيير الأول ، ولكن هنا لا تزال القيمة الأولية قيد إعادة الحساب. قد يكون هذا مكلفًا إذا قمنا بإنشاء مصفوفات كبيرة أو إجراء عمليات حسابية ثقيلة.

يمكننا حل هذه المشكلة بالمرور getItems باعتباره _ مهيئ _ وظيفة.

الآن ، دعنا نجري تغييرًا بسيطًا على الكود.

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

مع وظيفة التهيئة

انظر نافذة وحدة التحكم في CodeSandbox. لاحظ أن سجل "getItems يسمى" تتم طباعته فقط في العرض الأول. عند إضافة العناصر اللاحقة ، لا يكون هذا السجل موجودًا.

على الرغم من عدم وجود فرق مرئي بين المثالين ، إلا أنهما مختلفان من حيث الأداء.

تذكر عندما تحتاج إلى وظيفة للحالة الأولية ، قم دائمًا بتمرير الوظيفة أو استدعاء الوظيفة داخل وظيفة أخرى. لا تستدعي الوظيفة مباشرة.

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

كم عدد خطافات useState التي يمكنني الحصول عليها

يمكن أن يكون لديك العديد من خطافات useState داخل أحد المكونات حسب ما تتطلبه.

انظر CodeSandbox

استخدامات متعددة

يحتوي المكون أدناه على ثلاث حالات مختلفة - اسم المستخدم وكلمة المرور و keepMeSignedIn.

حاول تحديث قيم اسم المستخدم ، keepMeSignedIn. يتم تسجيل الحالات المحدثة في وحدة التحكم عند النقر فوق زر تسجيل الدخول.

الصفقات المميزة

  • يوفر useState آلية لبدء إعادة التصيير واستمرار الحالة بين عمليات إعادة التصيير.
  • استخدم وظيفة التحديث عندما تحتاج إلى:
    • احسب الحالة التالية بناءً على الحالة السابقة.
    • قم بإجراء تحديثات متعددة للحالة قبل العرض التالي.
  • إذا تم الحصول على الحالة الأولية من دالة - استخدم صيغة دالة المُهيئ.
  • يمكن أن يكون هناك عدة خطافات useState داخل أحد المكونات.

أحب هذا المنصب؟ شاركها مع الآخرين.
مكتوب بشكل أصلي لمدونتي الشخصية - https://gauravsen.com/use-state-hook

الطابع الزمني:

اكثر من حقيقة تفاعل المرمز