الوحدة 2 · الـ Components والـ Props
التفكير بالـ components
16 دقراءة 3 داختر بحكمة
الدرس في لمحة
حوّل تصميم الشاشة إلى شجرة components، وابنِ نسخة ثابتة أولًا، وحدّد أقل قدر من الـ state يحتاجه Watchlist قبل كتابة أي كود تفاعلي.
- 1ارسم صناديق وسمِّها
- 2متى تقسّم، ومتى لا تفعل
- 3ابنِ النسخة الثابتة أولًا
- 4اعثر على أقل قدر من الـ state
- 5أين تعيش البيانات
لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.
هذا هو Watchlist الذي تبنيه، موصوفًا كما يسلّمه المصمّم: ترويسة فيها العنوان وعبارة «3 to watch»؛ ونموذج فيه حقل لعنوان الفيلم وزر Add؛ وصف من أزرار الفلترة (All وTo watch وWatched)؛ وقائمة أفلام، لكل فيلم عنوانه وسنته ومربّع اختيار لتعليمه كمُشاهَد. وحين تكون القائمة فارغة، تحلّ محلّها رسالة ودودة.
قبل أن تكتب سطرًا واحدًا من الكود، قرّر ما هي الـ components. هذه أهم خطوة تصميمية في تطبيق React، وتُنجَز بالقلم.
ارسم صناديق وسمِّها
خذ التصميم وارسم صندوقًا حول كل قطعة تؤدّي عملًا واحدًا. ثم سمِّ كل صندوق باسم، كما تسمّي دالة.
الصناديق المتداخلة تصبح شجرة. يملك App الشاشة كلها. ويرسم MovieList إمّا عدّة MovieItem وإمّا EmptyState واحدًا. هذه الشجرة هي خطة بقية الدورة؛ ستبني كل صندوق فيها كـ component.
متى تقسّم، ومتى لا تفعل
اجعل القطعة component مستقلًا إذا تحقّق واحد على الأقل مما يلي:
- تتكرّر. يظهر
MovieItemمرة لكل فيلم، والغاية أن تكتبه مرة واحدة. - لها عمل خاص بها. يتولّى
AddMovieFormالكتابة والإرسال، ولا يحتاج أي جزء آخر إلى معرفة كيف يفعل ذلك. - الأب صار صعب القراءة. إن كنت تحتاج إلى التمرير لتفهم component، فاستخرج منه قطعة لها اسم.
لا تقسّم لمجرد أنك تستطيع. الـ component الذي لا يفعل سوى تغليف <span> واحد يضيف ملفًا وسطر import واسمًا عليك تذكّره، ولا يعطيك شيئًا في المقابل. الفرق المتمرّسة كثيرًا ما تُبقي component من 100 سطر بدل أن تقسّمه إلى خمسة من 20 سطرًا لا تُستخدم إلا معًا. ابدأ بحجم أكبر قليلًا، واستخرج القطع حين يظهر أحد الأسباب الثلاثة.
ابنِ النسخة الثابتة أولًا
بعد رسم الشجرة، ابنِها ببيانات مكتوبة يدويًا ومن دون أي تفاعل. مرّر البيانات من الأعلى إلى الأسفل حتى يكون الشكل صحيحًا من البداية:
const MOVIES = [
{ id: 1, title: 'Arrival', year: 2016, watched: true },
{ id: 2, title: 'Past Lives', year: 2023, watched: false },
{ id: 3, title: 'Paddington 2', year: 2017, watched: false },
];
export default function App() {
return (
<main>
<Header movies={MOVIES} />
<AddMovieForm />
<FilterBar />
<MovieList movies={MOVIES} />
</main>
);
}
// …Header, AddMovieForm, FilterBar and MovieList defined belowبناء النسخة الثابتة كتابة في معظمه، وهو يضبط البنية والـ markup بينما لا شيء يتحرّك. أمّا إضافة التفاعل فتفكير في معظمها. والقيام بالأمرين معًا هو الطريق الذي تنتهي به الـ components متشابكة.
اعثر على أقل قدر من الـ state
بعد ذلك، اكتب قائمة بكل قطعة بيانات في التطبيق، واطرح على كل واحدة ثلاثة أسئلة: هل تبقى ثابتة مع الوقت؟ هل تأتي من الأب؟ هل يمكنك حسابها من بيانات أخرى؟ إذا كان الجواب نعم على أيٍّ منها، فهي ليست state.
بالنسبة إلى Watchlist:
| البيانات | state؟ | السبب |
|---|---|---|
| قائمة الأفلام | نعم | تتغيّر حين تضيف فيلمًا أو تحذفه أو تعلّمه |
| الفلتر الحالي | نعم | يتغيّر حين تنقر زر فلترة |
| النص المكتوب في النموذج | نعم | يتغيّر أثناء الكتابة |
| عدد الأفلام المتبقية | لا | يُحسب من الأفلام |
| الأفلام الظاهرة حاليًا | لا | تُحسب من الأفلام + الفلتر |
ثلاث قطع من الـ state، وقيمتان مشتقّتان. إبقاء الـ state في حدّه الأدنى هو العادة الوحيدة التي تمنع أكبر عدد من الأخطاء في تطبيقات React. فكل قطعة state إضافية نسخة ثانية من الحقيقة قد تختلف عن الأولى.
أين تعيش البيانات
يحتاج Header إلى الأفلام (من أجل العدد)، ويحتاجها MovieList (لعرضها). والقاعدة: تعيش البيانات في أقرب أب مشترك لكل الـ components التي تحتاجها، وهو هنا App. وتنزل منه كـ props. وحين يحتاج ابنٌ إلى تغييرها، يمرّر له الأب دالة يستدعيها. ستفعل هذا تحديدًا في القسم 3.
في الدرس التالي تتعلّم الـ props كما يجب: كيف تمرّر البيانات إلى الـ components، وتضبط القيم الافتراضية، وتُبقي الـ components قابلة لإعادة الاستخدام.
أهم النقاط
- ارسم صناديق حول التصميم وسمِّ كل صندوق؛ الصناديق المتداخلة تصبح شجرة components.
- قسّم الـ component حين تتكرّر قطعة منه، أو يكون لها عمل مستقل، أو حين يصعب قراءة الأب، لا لمجرد العادة.
- ابنِ نسخة ثابتة من بيانات مكتوبة يدويًا أولًا، ثم أضف التفاعل.
- احتفظ بأقل قدر من الـ state؛ فكل ما يمكن حسابه من بيانات أخرى، كالعدد أو القائمة المصفّاة، قيمة مشتقّة وليس state.