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

تستخدم React key
السمة أثناء مرحلة التسوية الخاصة بها لتقرير العناصر التي يمكن إعادة استخدامها للعرض التالي. إنها مهمة للقوائم الديناميكية. ستقارن React مفاتيح العنصر الجديد بالمفاتيح السابقة و 1) تركيب المكونات التي تحتوي على مفتاح جديد 2) إلغاء تحميل المكونات التي لم تعد مفاتيحها مستخدمة.
سمع العديد من مطوري React النصيحة العامة التي يجب ألا تستخدمها index
كمفتاح. ولكن ما الخطأ الذي يمكن أن يحدث عند استخدام key
s بطريقة سيئة؟ ماذا يمكننا أن نفعل أيضًا عندما نلعب بالمفاتيح؟
لفهم أفضل ، دعنا نفكر في مثال عرض قائمة بـ input
s. عند النقر فوق الزر ، سنقوم بإدراج عنصر جديد به نص 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
إدراجها في الجزء الخلفي من القائمة؟ إليك ما يحدث:
Item is an uncontrolled component
:input
يتم تخزين النص الذي يكتبه المستخدم في حقله على هيئةstate
{ text: "Front" }
يتم إدراج عنصر بيانات جديد في بداية بيانات القائمة.- يتم إعادة عرض القائمة بقيمة الفهرس كـ
key
. لذا المكونات السابقة وإعادة استخدامها لالأولين عناصر البيانات ويتم إعطاء الدعائم الصحيحةFront
وFirst
، ولكن لم يتم تحديث الدولة فيItem
. هذا هو السبب في أن أول مثيلين مكونين يحتفظان بنفس النص. - يتم إنشاء مثيل مكون جديد من أجل
key: 2
لأنه لم يتم العثور على مفتاح مطابقة سابق. يتم ملؤهprops
بآخر عنصر بيانات في القائمة وهوSecond
.

نقطة أخرى مثيرة للاهتمام هي render
المكالمات التي تحدث. العنصر هو PureComponent
، لذلك يتم تحديثه فقط عندما text
تتغير الخاصية (أو الحالة):
rerendering Frontrerendering Firstrerendering SecondMounted Second
يتم إعادة تقديم جميع المكونات. يحدث هذا بسبب key: 0
إعادة استخدام العنصر مع لعنصر البيانات الأول واستلامه props
، ولكن عنصر البيانات الأول أصبح الآن Front
الكائن الجديد ، مما يؤدي إلى تشغيل ملف render
. يحدث الشيء نفسه مع المكونات الأخرى ، لأن عناصر البيانات القديمة يتم نقلها الآن جميعًا من مكان واحد.
إذن ما هو الإصلاح؟ الإصلاح سهل: نمنح كل عنصر بيانات قائمة id
مرة واحدة فريدة عند الإنشاء (وليس في كل عرض!). ستتم مطابقة جميع مثيلات المكونات مع عنصر البيانات المقابل لها. يتلقون نفس الشيء props
كما كان من قبل ، وهذا يتجنب آخر render
.
دعنا نتجاهل مزايا الأداء التي تأتي من استخدام id
s في القوائم الديناميكية في الوقت الحالي. يوضح المثال أن الأخطاء التي أدخلتها المفاتيح تحدث فقط فيما يتعلق بالمكونات غير المنضبطة ، والمكونات التي تحافظ على الحالة الداخلية .
إذا أعدنا الكتابة Item
كمكون مضبوط ، عن طريق إخراج الحالة منه ، يختفي الخطأ.
لماذا ا؟ مرة أخرى ، لأن الخطأ كان يعيد استخدام مكون لعنصر بيانات مختلف. لذلك ، لا تزال الحالة الداخلية تعكس حالة عنصر البيانات السابق ، ولكن الدعائم لعنصر مختلف . جعل المكون متحكمًا ، عن طريق إزالة حالته تمامًا ، لم يعد لدينا هذا التناقض. (ولكن لا تزال هناك مشكلة في عمليات إعادة العرض غير الضرورية).
مفاتيح الإساءة لإصلاح مكونات الطرف الثالث المعطلة
لا تحتاج React إلا إلى key
s عند مطابقة عدة عناصر ، لذا لا يلزم تعيين مفتاح على طفل واحد. ولكن لا يزال من المفيد تعيين مفتاح على مكون فرعي واحد.
إذا قمت بتغيير المفتاح ، فسوف تتخلص React من المكون بأكمله (يلغي تحميله) ، وتثبيت مثيل مكون جديد في مكانه. لماذا يمكن أن يكون هذا مفيدا؟
مرة أخرى ، نعود إلى المكونات الخارجة عن السيطرة . في بعض الأحيان ، تستخدم مكوّنًا تابعًا لجهة خارجية ولا يمكنك تعديل رمزه للتحكم فيه. إذا كان للمكون بعض الحالة الداخلية وتم تنفيذه بطريقة سيئة (على سبيل المثال ، يتم اشتقاق الحالة مرة واحدة فقط في المُنشئ ، ولكن getDerivedStateFromProps
/ componentWillReceiveProps
لم يتم تنفيذها لتعكس props
التغييرات المتكررة في حالتها الداخلية) ، فلن يساعدك صندوق أدوات React القياسي هنا. لا يوجد forceRemount
.
ومع ذلك ، يمكننا فقط تعيين عنصر جديد key
على هذا المكون لتحقيق السلوك المطلوب لتهيئة مكون جديد بالكامل. سيتم إلغاء تثبيت المكون القديم ، وسيتم تركيب مكون جديد مع props
التهيئة الجديدة لـ state
.
TL ؛ DR:
يمكن أن يؤدي الاستخدام index
كمفتاح إلى:
- يؤدي إلى عمليات إعادة تصيير غير ضرورية
- إدخال أخطاء عندما تكون عناصر القائمة مكونات غير خاضعة للرقابة ولكنها لا تزال تستخدم
props
على key
الملكية يمكن أن تستخدم لفرض الفرس البديل الكامل لعنصر، والتي يمكن أن تكون مفيدة في بعض الأحيان.
نُشر في الأصل في cmichel.io
