كيف تعمل مفاتيح React والأشياء الممتعة التي يمكنك فعلها بها

تستخدم React keyالسمة أثناء مرحلة التسوية الخاصة بها لتقرير العناصر التي يمكن إعادة استخدامها للعرض التالي. إنها مهمة للقوائم الديناميكية. ستقارن React مفاتيح العنصر الجديد بالمفاتيح السابقة و 1) تركيب المكونات التي تحتوي على مفتاح جديد 2) إلغاء تحميل المكونات التي لم تعد مفاتيحها مستخدمة.

سمع العديد من مطوري React النصيحة العامة التي يجب ألا تستخدمها indexكمفتاح. ولكن ما الخطأ الذي يمكن أن يحدث عند استخدام keys بطريقة سيئة؟ ماذا يمكننا أن نفعل أيضًا عندما نلعب بالمفاتيح؟

لفهم أفضل ، دعنا نفكر في مثال عرض قائمة بـ inputs. عند النقر فوق الزر ، سنقوم بإدراج عنصر جديد به نص Frontفي مقدمة القائمة.

import React from "react";import { render } from "react-dom";class Item extends React.PureComponent { state = { text: this.props.text }; onChange = event => { this.setState({ text: event.target.value }); }; componentDidMount() { console.log("Mounted ", this.props.text); } componentWillUnmount() { console.log("Unmounting ", this.props.text); } render() { console.log("rerendering ", this.props.text); const { text } = this.state; return ( 
  • ); }}class App extends React.Component { state = { items: [ { text: "First", id: 1 }, { text: "Second", id: 2 } ] }; addItem = () => { const items = [{ text: "Front", id: Date.now() }, ...this.state.items]; this.setState({ items }); }; render() { return (
      {this.state.items.map((item, index) => ( ))}
    Add Item ); }}render(, document.getElementById("root"));

    إذا كنت تستخدم indexكمفتاح ، فسيحدث ما يلي:

    كود ساندبوكس

    CodeSandbox هو محرر على الإنترنت مصمم لتطبيقات الويب. كودو

    ماذا لو تم إدراج آخر Itemبه نص Secondبدلاً من Frontإدراجها في الجزء الخلفي من القائمة؟ إليك ما يحدث:

    1. Item is an uncontrolled component: inputيتم تخزين النص الذي يكتبه المستخدم في حقله على هيئةstate
    2. { text: "Front" }يتم إدراج عنصر بيانات جديد في بداية بيانات القائمة.
    3. يتم إعادة عرض القائمة بقيمة الفهرس كـ key. لذا المكونات السابقة وإعادة استخدامها لالأولين عناصر البيانات ويتم إعطاء الدعائم الصحيحة Frontو First، ولكن لم يتم تحديث الدولة في Item. هذا هو السبب في أن أول مثيلين مكونين يحتفظان بنفس النص.
    4. يتم إنشاء مثيل مكون جديد من أجل key: 2لأنه لم يتم العثور على مفتاح مطابقة سابق. يتم ملؤه propsبآخر عنصر بيانات في القائمة وهو Second.

    نقطة أخرى مثيرة للاهتمام هي renderالمكالمات التي تحدث. العنصر هو PureComponent، لذلك يتم تحديثه فقط عندما textتتغير الخاصية (أو الحالة):

    rerendering Frontrerendering Firstrerendering SecondMounted Second

    يتم إعادة تقديم جميع المكونات. يحدث هذا بسبب key: 0إعادة استخدام العنصر مع لعنصر البيانات الأول واستلامه props، ولكن عنصر البيانات الأول أصبح الآن Frontالكائن الجديد ، مما يؤدي إلى تشغيل ملف render. يحدث الشيء نفسه مع المكونات الأخرى ، لأن عناصر البيانات القديمة يتم نقلها الآن جميعًا من مكان واحد.

    إذن ما هو الإصلاح؟ الإصلاح سهل: نمنح كل عنصر بيانات قائمة idمرة واحدة فريدة عند الإنشاء (وليس في كل عرض!). ستتم مطابقة جميع مثيلات المكونات مع عنصر البيانات المقابل لها. يتلقون نفس الشيء propsكما كان من قبل ، وهذا يتجنب آخر render.

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

    إذا أعدنا الكتابة Itemكمكون مضبوط ، عن طريق إخراج الحالة منه ، يختفي الخطأ.

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

    مفاتيح الإساءة لإصلاح مكونات الطرف الثالث المعطلة

    لا تحتاج React إلا إلى keys عند مطابقة عدة عناصر ، لذا لا يلزم تعيين مفتاح على طفل واحد. ولكن لا يزال من المفيد تعيين مفتاح على مكون فرعي واحد.

    إذا قمت بتغيير المفتاح ، فسوف تتخلص React من المكون بأكمله (يلغي تحميله) ، وتثبيت مثيل مكون جديد في مكانه. لماذا يمكن أن يكون هذا مفيدا؟

    مرة أخرى ، نعود إلى المكونات الخارجة عن السيطرة . في بعض الأحيان ، تستخدم مكوّنًا تابعًا لجهة خارجية ولا يمكنك تعديل رمزه للتحكم فيه. إذا كان للمكون بعض الحالة الداخلية وتم تنفيذه بطريقة سيئة (على سبيل المثال ، يتم اشتقاق الحالة مرة واحدة فقط في المُنشئ ، ولكن getDerivedStateFromProps/ componentWillReceivePropsلم يتم تنفيذها لتعكس propsالتغييرات المتكررة في حالتها الداخلية) ، فلن يساعدك صندوق أدوات React القياسي هنا. لا يوجد forceRemount.

    ومع ذلك ، يمكننا فقط تعيين عنصر جديد keyعلى هذا المكون لتحقيق السلوك المطلوب لتهيئة مكون جديد بالكامل. سيتم إلغاء تثبيت المكون القديم ، وسيتم تركيب مكون جديد مع propsالتهيئة الجديدة لـ state.

    TL ؛ DR:

    يمكن أن يؤدي الاستخدام indexكمفتاح إلى:

    1. يؤدي إلى عمليات إعادة تصيير غير ضرورية
    2. إدخال أخطاء عندما تكون عناصر القائمة مكونات غير خاضعة للرقابة ولكنها لا تزال تستخدمprops

    على keyالملكية يمكن أن تستخدم لفرض الفرس البديل الكامل لعنصر، والتي يمكن أن تكون مفيدة في بعض الأحيان.

    نُشر في الأصل في cmichel.io