Control Props Pattern In React

يعتلي بناء مُكونات قابلة لإعادة الاستخدام والتكييف في عالم تطوير التطبيقات باستخدام React عرش الأولويات. هنا يظهر نمط Control Props كأداة قوية تمنح المُكونات تحكما كاملا في سلوك (behavior) و حالة (state) مُكوناتها الفرعية، مما يضمن اتساقًا وسلاسة في تجربة المستخدم
Control Props Pattern In React

في هذه الصفحة

يعتلي بناء مُكونات قابلة لإعادة الاستخدام والتكييف في عالم تطوير التطبيقات باستخدام React عرش الأولويات. هنا يظهر نمط Control Props كأداة قوية تمنح المُكونات تحكما كاملا في سلوك (behavior) و حالة (state) مُكوناتها الفرعية، مما يضمن اتساقًا وسلاسة في تجربة المستخدم. اليوم، سنغوص في رحلة لاستكشاف هذا النمط، وفهم ميزاته وفوائده، وتعلم كيفية تطبيقه في تطبيقات React.

تعريف نمط Control Props

ببساطة، يُتيح نمط Control Props للمُكون الرئيسي (parent component) التحكم الكامل في مُكونه الفرعي (child component). يُحقق ذلك من خلال تمرير قيم الحالة (state) كخصائص (props) إلى المُكون الفرعي بالإضافة إلى وظائف (functions) لتحديث هذه القيم.


مُميزات نمط Control Props

  • تحكم كامل: يُتيح لك هذا النمط التحكم الكامل في سلوك المُكونات الفرعية من خلال المُكون الرئيسي، مما يُسهل إدارة الحالة (state) وتحديثها.
  • قابلية إعادة الاستخدام: يُصبح بناء مُكونات قابلة لإعادة الاستخدام أسهل، حيث لا تعتمد المُكونات الفرعية على الحالة (state) الداخلية الخاصة بها.
  • اتساق سلوك المُكونات: يُمكن ضمان اتساق سلوك المُكونات الفرعية عبر التطبيق من خلال التحكم في حالتها (state) من المُكون الرئيسي.
  • سهولة اختبار المُكونات: يُصبح اختبار المُكونات الفرعية أسهل، حيث يُمكن اختبار سلوكها بشكل مستقل عن المُكونات الأخرى.

لفهم هذا النمط بشكل أفضل، دعنا نستكشفه من خلال مثال يوضح كيفية تطبيقه في مكون Rating.

// StarRatingWithoutControlProps.jsx
import { useState } from "react"
export const StarRatingWithoutControlProps = () => {
  const [rating, setRating] = useState(0);

  const handleRatingChange = (newRating) => {
    setRating(newRating);
  };

  return (
    <div>
      {[1, 2, 3, 4, 5].map((star) => (
        <Star
          key={star}
          selected={star <= rating}
          onClick={() => handleRatingChange(star)}
        />
      ))}
    </div>
  );
};

const Star = ({ selected, onClick }) => (
	<span onClick={onClick} style={{ color: selected ? "orange" : "gray" }}>
    ★
  </span>
);

// App.jsx
import { StarRatingWithoutControlProps } from "./StarRatingWithoutControlProps";

function App() {
  return (
    <div>
      <StarRatingWithoutControlProps />
    </div>
  );
}

export default App

بينما يعمل المُكون بشكل جيد في سيناريوهات محددة، قد تتطلب إعادة استخدامه في سياقات أخرى تعديلات كبيرة. كما يعتمد سلوك المُكون على القيمة الافتراضية المُحددة داخليًا، مما يُحد من مرونته. كما أن المُكون مسؤول عن كل من إدارة المنطق (handle logic) والعرض (render UI)، مما يُقلل من قابلية إعادة الاستخدام. يُمكن معالجة نقطة "الاعتماد على القيمة الافتراضية" لزيادة مرونة المُكون قليلا بدون نمط الـ Control Props فقط من خلال جعل المُكون يستقبل خاصية تُمثل القيمة الافتراضية أو الابتدائية للمُكون.

// StarRatingWithoutControlProps.jsx
import { useState } from "react"
export const StarRatingWithoutControlProps = ({ initialRating = 0 }) => {
  const [rating, setRating] = useState(initialRating);

  const handleRatingChange = (newRating) => {
    setRating(newRating);
  };

  return (
    <div>
      {[1, 2, 3, 4, 5].map((star) => (
        <Star
          key={star}
          selected={star <= rating}
          onClick={() => handleRatingChange(star)}
        />
      ))}
    </div>
  );
};

const Star = ({ selected, onClick }) => (
	<span onClick={onClick} style={{ color: selected ? "orange" : "gray" }}>
    ★
  </span>
);

// App.jsx
import { StarRatingWithoutControlProps } from "./StarRatingWithoutControlProps";

function App() {
  return (
    <div>
      <StarRatingWithoutControlProps />
			<StarRatingWithoutControlProps initialRating={10} />
    </div>
  );
}

export default App

هذا الحل يُعتبر جزئي و غير فعال، الطريقة الأمثل في هاته الحالة هي استخدام نمط الـ Control Props لفصل إدارة المنطق عن العرض و جعل المُكون مسؤولًا عن عرض واجهة المستخدم فقط (Agnostic Component) مما يُحسن قابلية إعادة الاستخدام في مختلف السياقات.

// StarRatingWithControlProps.jsx
const StarRatingWithControlProps = ({ rating, onRatingChange }) => {
  return (
    <div>
      {[1, 2, 3, 4, 5].map((star) => (
        <Star
          key={star}
          selected={star <= rating}
          onClick={() => onRatingChange(star)}
        />
      ))}
    </div>
  );
};

const Star = ({ selected, onClick }) => (
  <span
    onClick={onClick}
    style={{ color: selected ? "yellow" : "gray" }}
  >
    ★
  </span>
);

// App.jsx
function App() {
  const [rating1, setRating1] = useState(0);

  const handleRating1Change = (newRating) => {
    setRating1(newRating);
  };

	const [rating2, setRating2] = useState(3);

  const handleRating2Change = (newRating) => {
		// maybe call API or doing another logic here as well
		// maybe change the logic of how calculate the rate.
  };

  return (
    <div>
      <StarRatingWithControlProps rating={rating1} onRatingChange={handleRating1Change} />
			<StarRatingWithControlProps rating={rating2} onRatingChange={handleRating2Change} />
    </div>
  );
}

في الكود أعلاه، المُكون الأب App مسؤول عن  إدارة قيمة تقييم النجوم و تحديد السلوك عند تفاعل المستخدم مع المُكونات الفرعية. بينما المُكونات الفرعية مسؤولة عن عرض واجهة مستخدم تقييم النجوم بناءً على القيم المُرسلة من المُكون الأب.

متى لا نستخدم نمط Control Props؟

ليس من الضروري استخدام نمط Control Props في جميع الحالات. في بعض الأحيان، قد يُضيف هذا النمط تعقيدًا غير ضروري على الشيفرة البرمجية. إليك بعض الحالات التي قد لا تحتاج لاستخدام هذا النمط:

  • المكونات البسيطة: إذا كان المُكون بسيطًا ولا يتطلب سلوكًا مُعقدًا، فلا داعي لاستخدام نمط Control Props.
  • المكونات ذات الحالة المُستقلة: إذا كان المُكون يدير حالته الخاصة ولا يتفاعل مع مكونات أخرى، فلا داعي لاستخدام نمط Control Props.
  • الحالات التي لا تتطلب إعادة استخدام: إذا كنت لا تخطط لإعادة استخدام المُكون في سياقات أخرى، فلا داعي لاستخدام نمط Control Props.

يُعد نمط Control Props أسلوب و مُمارسة جيدة لإنشاء مكونات قابلة لإعادة الاستخدام وقابلة للتكيف في تطبيقات React. ومع ذلك، من المهم استخدام هذا النمط بحكمة واختيار الحالات التي يُناسبها.

اشترك الآن بنشرة اقرأ-تِك الأسبوعية

لا تدع أي شيء يفوتك. واحصل على أحدث المقالات المميزة مباشرة إلى بريدك الإلكتروني وبشكل مجاني!