Menu
flag Ar iconالعربيةdown icon

المكوّنات المتحكم بها وغير المتحكم بها في React

الحقل المتحكم به يأخذ قيمته من حالة React ولا يتغير إلا عبر onChange. والحقل غير المتحكم به يحتفظ بقيمته في DOM، وتقرؤها بمرجع أو بـ FormData. تعلّم الفرق والتحذيرات الشائعة ومتى تستخدم كلًا منهما.

تحتوي هذه الصفحة على محررات قابلة للتشغيل - حرّر، شغّل، وشاهد النتيجة فوراً.

المكوّن المتحكم به عنصر نموذج تعيش قيمته في حالة React: تمرر value وتحدّث الحالة في onChange، فتقرر React ما يعرضه الحقل. والمكوّن غير المتحكم به يحتفظ بقيمته في DOM، مثل HTML العادية: تمرر defaultValue ابتدائية وتقرأ القيمة الحالية لاحقًا عبر مرجع أو FormData.

اكتب في الحقلين. تتبع الفقرة الحقل الأول مع كل ضغطة مفتاح، لأن كل تغيير يضبط الحالة ويعيد العرض. أما الحقل الثاني فلا يتغير إلا في DOM؛ لا تعرض React شيئًا، ولا ترى قيمته إلا عندما يطلبها "Read both".

الحقول المتحكم بها

في الحقل المتحكم به، حالة React هي المصدر الوحيد للحقيقة. ويكون التدفق مع كل ضغطة مفتاح كالآتي:

  1. يكتب المستخدم، فيطلق المتصفح حدث إدخال.
  2. يقرأ معالج onChange القيمة e.target.value ويستدعي دالة الضبط.
  3. تعيد React العرض وتكتب الحالة الجديدة في value الخاصة بالحقل.

لأن كودك يقع في منتصف هذه الحلقة، يمكنك فعل أشياء لا يستطيعها الحقل غير المتحكم به: رفض المحارف أو إعادة تشكيلها، أو عرض القيمة في مكان آخر، أو تعطيل زر حتى تصبح القيمة صالحة، أو ضبط القيمة من الكود (زر "Clear"، أو اقتراح ينقره المستخدم).

جرّب كتابة أحرف: لا تظهر أبدًا، لأن المعالج يحذف كل ما ليس رقمًا قبل ضبط الحالة. ويبقى زر Verify معطّلًا حتى توجد ستة أرقام بالضبط.

الحقل المتحكم به هو ما تستخدمه أمثلة النماذج في صفحة النماذج، وهو الخيار الافتراضي في معظم كود React.

الحقول غير المتحكم بها

يعمل الحقل غير المتحكم به مثل HTML العادية. تعرضه React مرة واحدة بـ defaultValue (أو defaultChecked لمربعات الاختيار والأزرار الدائرية) ثم تتركه وشأنه. لقراءة القيمة، احتفظ بمرجع إلى العنصر أو اقرأ كل الحقول المسماة من النموذج عند الإرسال بـ FormData.

لا توجد حالة للحقول ولا onChange. لا تُجمع القيم إلا عندما يُرسل النموذج. ألغِ تحديد مربع الاختيار وأرسل مرة أخرى: يختفي المفتاح subscribe، لأن مربع الاختيار غير المحدد ليس جزءًا من FormData إطلاقًا.

تغيير defaultValue بعد العرض الأول لا يفعل شيئًا للحقل، لأن React لا تطبقها إلا عند إنشاء العنصر. ولإعادة ضبط نموذج غير متحكم به، استدعِ e.target.reset()، أو أعطِ النموذج key جديدًا لتنشئ React حقولًا جديدة.

حقل لا تستطيع الكتابة فيه

إذا مررت value دون onChange، فالحقل متحكم به، لكن لا شيء يحدّث الحالة أبدًا. تكتب React القيمة نفسها من جديد بعد كل ضغطة مفتاح، فيبدو الحقل متجمدًا.

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

في التطوير، تسجّل React تحذيرًا للحقل الأول: "You provided a value prop to a form field without an onChange handler". تعمل المعاينة مثل بناء الإنتاج، فلن ترى هذا التحذير هنا، لكنك ستراه في خادم التطوير الخاص بك.

التحول من غير متحكم به إلى متحكم به

تقرر React ما إذا كان الحقل متحكمًا به بالنظر إلى value. إذا كانت value هي undefined أو null، فالحقل غير متحكم به. لذا فإن حقلًا تبدأ value الخاصة به على أنها undefined ثم تصبح نصًا يتحول من غير متحكم به إلى متحكم به أثناء حياته، وتحذّر React في التطوير: "A component is changing an uncontrolled input to be controlled".

يشير التحذير إلى خطأ حقيقي. فالعودة في الاتجاه المعاكس، من نص إلى undefined، تجعل الحقل غير متحكم به من جديد، فتتوقف React عن الكتابة فيه.

اكتب شيئًا في الحقلين واضغط كل زر Clear. يُفرَّغ الحقل الثاني. أما الأول فيحتفظ بنصه: ضبط الحالة على undefined جعله غير متحكم به، فلم تعد React تتحكم في ما يعرضه.

المصدر المعتاد لـ undefined هو بيانات لم تُحمَّل بعد (value={user.name} قبل وصول المستخدم) أو حقل في كائن لم يوجد بعد. وهناك إصلاحان:

const [name, setName] = useState('');   // start with a string
<input value={user?.name ?? ''} />       // or fall back to one

وفي مربعات الاختيار تنطبق القاعدة نفسها على checked: ابدأها بـ false، لا undefined.

حقول الملفات غير متحكم بها دائمًا

لا يمكن التحكم في <input type="file">، لأن المتصفحات لا تسمح للصفحة بضبط قيمته (فالصفحة التي تستطيع اختيار ملفات من قرصك ستكون ثغرة أمنية). اقرأ الملفات المختارة من e.target.files في onChange، أو عبر مرجع عندما يُرسل النموذج.

اختر ملفًا أو اثنين من حاسوبك؛ لا يُرفع شيء، فالمثال يسرد الأسماء والأحجام فقط. القيمة الوحيدة التي يمكنك ضبطها على حقل ملف هي النص الفارغ، وبها يعيد زر Clear ضبطه.

متى تختار أيًا منهما

متحكم بهغير متحكم به
تعيش القيمة فيحالة ReactDOM
ضبط القيمة الابتدائيةvalue / checkeddefaultValue / defaultChecked
قراءة القيمةفي أي وقت، من الحالةبمرجع، أو FormData عند الإرسال
يُعرض مع كل ضغطة مفتاحنعملا
تغيير القيمة من الكوداضبط الحالةاكتب في DOM عبر مرجع
مناسب لـالتحقق المباشر والتنسيق والحقول المعتمدة على غيرهاالنماذج البسيطة المقروءة عند الإرسال وحقول الملفات وإجراءات النماذج

اختر المتحكم به عندما يجب أن تتفاعل الشاشة مع القيمة أثناء الكتابة. واختر غير المتحكم به عندما لا تحتاج إلى القيم إلا في النهاية، وهذه أيضًا طريقة عمل إجراءات النماذج في React 19: يسلّم <form action={fn}> دالتك FormData ويعيد ضبط الحقول غير المتحكم بها بعد ذلك.

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

تصف الكلمتان نفسهما مكوّناتك الخاصة أيضًا. المكوّن الذي يأخذ قيمته وonChange من أبيه عبر props متحكم به من الأب؛ والذي يحتفظ بحالته الخاصة غير متحكم به. ونقل الحالة إلى الأعلى لجعل مكوّن متحكمًا به هو موضوع رفع الحالة.

الأسئلة الشائعة

ما هو المكوّن المتحكم به في React؟

عنصر نموذج تأتي قيمته الحالية من حالة React، تُضبط بـ value (أو checked) وتُحدَّث عبر onChange. حالة React هي المصدر الوحيد للحقيقة، فتعرف القيمة دائمًا ويمكنك تغييرها من الكود.

ما هو المكوّن غير المتحكم به في React؟

عنصر نموذج يحتفظ بقيمته الخاصة في DOM، مثل HTML العادية. تعطيه قيمة ابتدائية بـ defaultValue (أو defaultChecked) وتقرأ القيمة الحالية عندما تحتاج إليها، عبر مرجع أو FormData عند الإرسال.

لماذا لا أستطيع الكتابة في حقل React الخاص بي؟

مررت value دون onChange. الحقل متحكم به، فتظل React تعيد قيمة الحالة إليه بعد كل ضغطة مفتاح. أضف onChange يحدّث الحالة، أو انتقل إلى defaultValue، أو أضف readOnly إن كان يجب ألا يتغير فعلًا.

كيف أصلح الرسالة "A component is changing an uncontrolled input to be controlled"؟

بدأت قيمة value في الحقل على أنها undefined (أو null) ثم أصبحت نصًا لاحقًا. تأكد أنها نص دائمًا: ابدأ الحالة بـ ''، أو اكتب value={name ?? ''}.

هل أستخدم حقولًا متحكمًا بها أم غير متحكم بها؟

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

رسم توضيحي للغات البرمجة في Coddy

تعلّم البرمجة مع Coddy

ابدأ الآن