EduFlow
أساسيات React
⁦0%⁩

الوحدة 2 · الـ Components والـ Props

العرض الشرطي

14 دقراءة 4 دبيئة تجريب الكود

الدرس في لمحة

اعرض أجزاء الواجهة وأخفِها وبدّل بينها بحسب البيانات باستخدام الـ return المبكر والمعامل الثلاثي و&&، مع تجنّب خطأ الصفر الشارد والشروط المتداخلة غير المقروءة.

  1. 1الـ return المبكر: بدائل كاملة
  2. 2المعامل الثلاثي: هذا أو ذاك
  3. 3الـ &&: شيء أو لا شيء
  4. 4الشروط في الخصائص
  5. 5اختيار الأداة المناسبة
  6. 6عدم العرض مقابل الإخفاء

لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.

الواجهات الحقيقية يتغيّر شكلها مع البيانات. يعرض Watchlist شارة «Watched» على بعض الأفلام دون غيرها، ورسالة مشجّعة حين تكون القائمة فارغة، وزر Add معطّلًا حتى تكتب عنوانًا. لا شيء من هذا يحتاج إلى صياغة خاصة في React. إنها JavaScript عادية تقرّر أي JSX تُرجع، وهناك ثلاث أدوات لذلك.

الـ return المبكر: بدائل كاملة

حين يعرض الـ component شيئًا مختلفًا تمامًا في حالة ما، عالج تلك الحالة أولًا ثم أرجِع:

src/components/MovieList.jsx
export default function MovieList({ movies }) {
  if (movies.length === 0) {
    return <p className="empty">Nothing to watch yet. Add a movie above.</p>;
  }

  return (
    <ul>
      {movies.map((movie) => (
        <li key={movie.id}>{movie.title}</li>
      ))}
    </ul>
  );
}

تُعالَج الحالة الفارغة في سطرين، ولا يهتمّ بقية الدالة إلا بالحالة العادية. هذا هو النمط الأسهل قراءة، فابدأ به أولًا. (الـ map والـ key موضوع الدرس التالي.)

ويمكن للـ component أيضًا أن يُرجع null كي لا يعرض شيئًا على الإطلاق:

JSX
function WatchedBadge({ watched }) {
  if (!watched) return null;
  return <span className="badge">Watched</span>;
}

المعامل الثلاثي: هذا أو ذاك

داخل JSX، حيث لا يمكنك كتابة if، استخدم المعامل الشرطي للاختيار بين مخرجين:

JSX
<p className="status">
  {movie.watched ? 'Watched' : 'To watch'}
</p>

ويعمل مع العناصر أيضًا: {isEditing ? <TitleInput /> : <h2>{title}</h2>}. أبقِ المعاملات الثلاثية قصيرة. وحين تضع معاملًا ثلاثيًا داخل آخر، أو يمتدّ كل فرع إلى عدّة أسطر، انقل القرار إلى متغيّر فوق return، أو إلى component صغير خاص به.

الـ &&: شيء أو لا شيء

حين يكون البديل «لا شيء»، يكون معامل AND المنطقي أقصر من معامل ثلاثي مع null:

JSX
<li>
  {movie.title}
  {movie.watched && <span className="badge">Watched</span>}
</li>

تحسب JavaScript التعبير a && b على أنه a إن كانت a قيمة falsy، وإلا فهو b. حين تكون movie.watched قيمتها false، يصبح التعبير false، ولا تعرض React شيئًا مقابل false. وحين تكون true، تحصل على الشارة.

الشروط في الخصائص

الشروط لا تخصّ العناصر الكاملة فقط، فالخصائص تأخذ تعبيرات أيضًا:

JSX
<li className={movie.watched ? 'movie movie-watched' : 'movie'}>
  {movie.title}
</li>

<button disabled={title.trim() === ''}>Add</button>

<button aria-pressed={filter === 'watched'}>Watched</button>

الثالثة مهمّة لإمكانية الوصول (accessibility): تُخبر aria-pressed مستخدمي الـ screen reader أي زر تبديل هو النشط، وهو ما لا يكفي تغيير اللون وحده لإيصاله. وحين تكون قيمة خاصية منطقية مثل disabled هي false أو null، لا تضعها React على العنصر.

اختيار الأداة المناسبة

الأنماط الثلاثة تُنتج النوع نفسه من النتائج، فالاختيار مسألة سهولة قراءة. هذه قاعدة عامة تصمد جيدًا في مراجعات الكود:

  • المخرجات كلها تتغيّر (تحميل، خطأ، فراغ، عادي): return مبكر، حالة واحدة في كل مرة، من الأعلى إلى الأسفل.
  • موضع واحد يتبدّل بين شيئين: معامل ثلاثي، بسطر أو اثنين لكل فرع.
  • موضع واحد إمّا موجود وإمّا لا: && مع قيمة منطقية حقيقية على اليسار.

حين تلاحظ أنك تكتب معاملًا ثلاثيًا داخل آخر، أو سلسلة && بثلاثة شروط، توقّف وامنح المنطق اسمًا. إمّا أن تحسب متغيّرًا (const status = …) فوق return، وإمّا أن تستخرج component صغيرًا مثل WatchedBadge يُخفي القرار بداخله. عندها يُقرأ الأب كجملة: عنوان، شارة، أزرار.

والترتيب مهمّ مع الـ return المبكر أيضًا. ضع أولًا الحالات التي تجعل البقية مستحيلة. إذا كانت قائمة الأفلام قد تكون قيد التحميل أو فاشلة أو فارغة، فافحصها بهذا الترتيب، كي لا يتعامل الـ return الأخير إلا مع بيانات حقيقية.

عدم العرض مقابل الإخفاء

هناك فرق مهمّ بين هذين:

JSX
{showWatched && <WatchedPanel />}
<div hidden={!showWatched}>
  <WatchedPanel />
</div>

الأول يزيل WatchedPanel من الشجرة حين يكون الشرط false. تُلغي React تركيبه (unmount): يذهب الـ DOM الخاص به، ويُهدم أي state بداخله، مثل النص المكتوب في حقل. وحين يعود، يبدأ من الصفر. أمّا الثاني فيُبقيه مركّبًا ولا يُخفي إلا غلافه (الخاصية hidden في HTML تعمل مثل display: none)، فيبقى الـ state.

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

في الدرس التالي تعرض قائمة الأفلام كاملة من البيانات باستخدام map، وتتعلّم لماذا تطلب منك React باستمرار key.

أهم النقاط

  • استخدم return مبكرًا للشاشات البديلة الكاملة، والمعامل الثلاثي للاختيار بين شيئين، و&& لشيء أو لا شيء.
  • يمكن للـ component أن يُرجع null كي لا يعرض شيئًا على الإطلاق.
  • الكود {count && <List />} يعرض 0 حرفيًا حين تكون count صفرًا؛ قارن صراحةً بـ count > 0 &&.
  • يمكن للشروط أن تتحكّم في الخصائص أيضًا، مثل className وdisabled وaria-pressed.
  • عدم عرض component يزيله ويزيل الـ state الخاص به؛ أمّا إخفاؤه بـ CSS فيُبقي الاثنين.

قراءات إضافية

تحقّق من فهمك

4 أسئلة

السؤال 1 من 4

المصفوفة movies فارغة. ماذا يعرض <div>{movies.length && <MovieList movies={movies} />}</div>؟

السؤال 2 من 4

يجب أن يعرض MovieList رسالة كاملة «Nothing to watch yet» حين تكون القائمة فارغة، ويعرض القائمة في غير ذلك. أيّ بنية هي الأسهل قراءة؟

السؤال 3 من 4

يجب ألّا يعرض WatchedBadge شيئًا حين تكون watched قيمتها false. أيّ نسخة تفعل ذلك؟

السؤال 4 من 4

تحتوي لوحة «Watched» القابلة للطيّ على حقل نصي. كتب المستخدم ملاحظة، ثم طوى اللوحة عبر {open && <Panel />}، ثم فتحها مجددًا. ماذا حدث للملاحظة؟

تدريب

بيئة تجريب الكود

الشارات وحالة القائمة الفارغة

في MovieList ثلاثة أخطاء. أصلحها بحيث:

  1. تظهر شارة Watched (<span className="badge">Watched</span>) فقط على الأفلام التي قيمة watched فيها true.
  2. حين تكون movies فارغة، تعرض القائمة الرسالة Nothing to watch yet. بدلًا من قائمة.
  3. لا تُظهر الحالة الفارغة أبدًا 0 شاردًا.

يرسم App القائمة مرتين، مرة بثلاثة أفلام ومرة بلا أفلام. لا تغيّر App.

function MovieList({ movies }) {
  return (
    <div>
      {movies.length && (
        <ul>
          {movies.map((movie) => (
            <li key={movie.id}>
              {movie.title}
              <span className="badge">Watched</span>
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

const MOVIES = [
  { id: 1, title: 'Arrival', watched: true },
  { id: 2, title: 'Past Lives', watched: false },
  { id: 3, title: 'Paddington 2', watched: false },
];

export default function App() {
  return (
    <main>
      <section id="full">
        <MovieList movies={MOVIES} />
      </section>
      <section id="empty">
        <MovieList movies={[]} />
      </section>
    </main>
  );
}
جارٍ تحميل المحرّر…

Ctrl/⌘ + Enter للتشغيل · يعمل في بيئة معزولة داخل متصفّحك. لا شيء يغادر جهازك.

المعاينة

الـ console

(لا مخرجات)

الفحوص

  • ما زالت القائمة الكاملة تعرض ثلاثة أفلام
  • يعرض Arrival (المُشاهَد) شارة Watched
  • لا يعرض Past Lives وPaddington 2 أي شارة
  • تعرض القائمة الفارغة “Nothing to watch yet.” ولا تحتوي على
    • لا يظهر 0 شارد في القائمة الفارغة