ابدأ مع React


الدرس: شارك الحالة (state) بين مكونات المختلفة


الصفحة السابقة
هذا جيد ، لدينا مكوناتنا مع الحالة (state) المحلية. تتيح لك السلة الخاصة بنا إضافة monsteras ، ويتم احتساب إجمالي السلة وفقًا لذلك.

ولكن كيف يمكنك تغيير سلوك أحد المكونات اعتمادًا على حالة مكون آخر  ؟ على سبيل المثال ، إذا أردت أخيرًا إضافة ارتباط بين   Cart   المكون الخاص بي والمكون الخاص بي   ShoppingList  . يمكنني إنشاء زر "إضافة إلى السلة" في كل منها   PlantItem  ... ولكن كيف يمكنني إكمال السلة وفقًا لذلك؟

رفع الحالة وتحديثها من مكونات الابن


React
كما يوحي اسمها ، الحالة المحلية ...هي محلية. لا يمكن للوالدين أو الأبناء التلاعب بالحالة المحلية للمكون (ليس لديهم الإمكانية التقنية للقيام بذلك).

في هذه الحالة ، كيف يمكن مشاركة عنصر الحالة بين عدة مكونات؟

حسنًا ، سيتعين علينا إحضار هذه البيانات إلى الحالة المحلية لأقرب مكون وهو أحد الوالدين المشتركين ، والحفاظ على الحالة هناك. من هناك سيكون من الممكن:

  1. جلب هذه المعلومات أسفل مع الدعائم إلى المكونات التي تحتاج إليها.
  2. تقديم طلبات "رجوع" للتحديث دائمًا في الدعائم. للقيام بذلك ، يمكننا استخدام وظيفة تحديث الحالة المسترجعة في useState ، وتمريرها كدعامات للمكونات التي تحتاجها.
React
أبلغ عن التحديثات للوالدين في الدعائم

قد تتساءل ما هي أفضل الممارسات: أين تضع الحالة (state)  ؟ في المكون الرئيسي ، أو في المكون الفرعي؟ حسنًا ، من الناحية العملية ... الأمر يعتمد على الوضعية. يعتبر من الأنظف الحفاظ على المنطق إلى أقصى حد في المكونات الأصلية ، وأن الأبناء يستخدمون فقط لعرض العناصر في الدعائم. لكن في كثير من الحالات ، من الأفضل كثيرًا إبقاء الحالة في المكون الفرعي. سوف تتعلم أن تراه مع الوقت والخبرة. 

لذلك دعونا نأخذ مثالنا.

بدأت في رفع   cart   في  App.js   :


<div>	أبلغ عن التحديثات للوالدين في الدعائم	</div>	<br/>
<div class="conseil">	قد تتساءل ما هي أفضل الممارسات: أين تضع الحالة (state)  ؟ في المكون الرئيسي ، أو في المكون الفرعي؟ حسنًا ، من الناحية العملية ... الأمر يعتمد على الوضعية. يعتبر من الأنظف الحفاظ على المنطق إلى أقصى حد في المكونات الأصلية ، وأن الأبناء يستخدمون فقط لعرض العناصر في الدعائم. لكن في كثير من الحالات ، من الأفضل كثيرًا إبقاء الحالة في المكون الفرعي. سوف تتعلم أن تراه مع الوقت والخبرة. 	</div>	<br/>
<div>	لذلك دعونا نأخذ مثالنا.	</div>	<br/>
<div>	بدأت في رفع   cart   في  App.js   :	</div>	<br/>
 
وما زلت في App.js JSX ، مررت cart وكذلك updateCart في الدعائم :

<Cart cart={cart} updateCart={updateCart} />
 
... التي أستعيدها في   Cart.js   . هل تتذكر التدمير (destructuring)؟ يسمح لنا باسترداد الدعامة الخاصة بنا في سطر واحد.

أغتنم هذه الفرصة لإزالة زر "إضافة" في    Cart.js .

إذن لدينا سلة فارغة صغيرة:


function Cart({ cart, updateCart }) {
    const monsteraPrice = 8
    const [isOpen, setIsOpen] = useState(true)

    return isOpen ? (
        <div className='lmj-cart'>
            <button
                className='lmj-cart-toggle-button'
                onClick={() => setIsOpen(false)}
            >
                Fermer
            </button>
            <h2>Panier</h2>
            <h3>Total : {monsteraPrice * cart}€</h3>
            <button onClick={() => updateCart(0)}>Vider le panier</button>
        </div>
    ) : (
        <div className='lmj-cart-closed'>
            <button
                className='lmj-cart-toggle-button'
                onClick={() => setIsOpen(true)}
            >
                Ouvrir le Panier
            </button>
        </div>
    )
}

export default Cart
 
من جانب ShoppingList، مررت لها updateCart . ثم نسترجعها في ShoppingList . ثم أقوم بتغيير قائمة النباتات التي لدي (لا تزال موجودة ShoppingList.js ) :

function ShoppingList({ cart, updateCart }) {
// Petite précision : categories nous vient de la partie précédente pour récupérer toutes les catégories uniques de plantes.

    const categories = plantList.reduce(
        (acc, elem) =>
            acc.includes(elem.category) ? acc : acc.concat(elem.category),
            []
    )
    
    return (
        <div className='lmj-shopping-list'>
            <ul>
                {categories.map((cat) => (
                <li key={cat}>{cat}</li>
                ))}
            </ul>
            <ul className='lmj-plant-list'>
                {plantList.map(({ id, cover, name, water, light }) => (
                    <div key={id}>
                        <PlantItem cover={cover} name={name} water={water} light={light} />
                        <button onClick={() => updateCart(cart + 1)}>Ajouter</button>
                    </div>
                ))}
            </ul>
        </div>
    )
}

export default ShoppingList
 
وها أنت ذا! يمكنك الآن تحديث سلتك مباشرة بالنقر فوق زر مرتبط بكل نبتة. 🎉

كما ترى ، الأمر ليس بهذا التعقيد ، لقد كان كافيًا لـ:

  • رفع الحالة  (state)
  • إسقاط محتوى الحالة ووظيفة تحديثها ؛
  • ابدأ تحديث حالتنا بتفاعل المستخدم (انقر هنا على الزر).
هنا ، نحن على تطبيق صغير: هناك صفحة واحدة فقط ونشارك الحالة مباشرة بين الآباء والأبناء. ولكن يمكن أن يتحول بسرعة إلى فوضى بالنسبة لتطبيق أكبر. هذا هو السبب في أن فكرة إدارة الحالة تذهب إلى أبعد من ذلك بكثير. هناك أدوات مخصصة لإدارة الحالة تذهب ابعد من ذلك ، هناك أدوات مخصصة لإدارة الحالة مثل Flux أو Redux أو الحلول الأصلية مثل React Context و التي لن نناقشها هنا، ولكنها موضوع دورة كاملة.

لقد رأينا كيفية تقاسم عناصر الحالة بين عدة مكونات. في الفيديو أدناه ، سنقوم الآن بتكييف تطبيقنا لجعل سلة التسوق تتصرف بشكل أكثر واقعية.

والفكرة هنا هي أن  االحالة لدينا تُخزّن اي أنواع  من النباتات، و بأي كمية ، وتقوم بتحديث المبلغ الإجمالي وفقا لسعر.

إذا هيا بنا !

تسرد سلة التسوق الخاصة بنا الآن العناصر المحددة ، وتقوم بتحديث الإجمالي بناءً على النباتات المختارة وسعرها. 🤩

ممارسة


React
ستتمكن الآن من تطبيق ما تعلمته في هذا الفصل على موقع النباتات الخاص بنا. كما هو الحال دائمًا ، ستجد قاعدة التعليمات البرمجية في فرع P3C2-Begin  .

الهدف هنا هو أخذ قائمة الفئات لدينا وتحسينها مع الحالة . لذلك ، إليك ما ستفعله:

  • إنشاء مكون منفصل ،   Categories  لإدارة الفئات.
  • اعرض القائمة في قائمة منسدلة  <select /> مع خيارات  <options /> :
    • تصبح كل فئة خيارًا. من الممكن اختيار فئة ؛
    • عند تحديد فئة ، يتم عرض النباتات المقابلة للفئة المحددة فقط.
  • أنشئ أيضًا زرًا يسمى "إعادة تعيين" . يتيح لك هذا الزر إعادة ضبط حالتك وعرض جميع فئات النباتات.
يمكنك إضافة خيار له قيمة سلسلة فارغة عندما لا يتم تحديد فئة.
يمكن إيجاد الحل في فرع P3C2-Solution .

باختصار


  • لاستخدام نفس التقرير بين عدة مكونات ، يجب عليك:
    • إحضار الحالة إلى أقرب مكون رئيسي مشترك ؛
    • ثم أنزل متغير الحالة والوظيفة لتحديث هذه الحالة في props .
في الفصل التالي ، سوف نتعلم كيفية استخدام خطاف التأثير لاختيار الوقت الذي نرغب فيه في تنفيذ إجراء ما ، على سبيل المثال لحفظ سلة لدينا في التخزين المحلي لمتصفحنا. لذا ، انتقل إلى الفصل التالي. ☀️