تخصيص CSS المضمن في React: دليل شامل للتغيير الشرطي بناءً على حالة المكون

دقائق القراءة: 8

تعد القدرة على تغيير تنسيقات CSS ديناميكيًا بناءً على حالة المكون (Component State) إحدى الميزات القوية في تطوير واجهات المستخدم باستخدام React. إذا كنت تواجه صعوبة في تحدي freeCodeCamp الذي يركز على هذه النقطة، فأنت لست وحدك. الهدف من هذا المقال هو إرشادك خطوة بخطوة لإضافة التعليمات البرمجية اللازمة لتغيير تنسيقات CSS المضمنة (Inline CSS) بشكل شرطي، مما يضمن تفاعلًا مرنًا ومستجيبًا لتطبيقك.

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

 class GateKeeper extends React . Component {
 constructor (props) {
 super (props);
 this .state = {
 input : ''
 };
 this .handleChange = this .handleChange.bind( this );
 }

 handleChange(event) {
 this .setState({
 input : event.target.value
 })
 }

 render() {
 let inputStyle = {
 border : '1px solid black'
 };
 // change code below this line
 // change code above this line
 return (
 < div >
 < h3 > Don't Type Too Much: </ h3 >
 < input type = "text" style = {inputStyle} value = {this.state.input} onChange = {this.handleChange} />
 </ div >
 );
 }
 };

لاحظ أن كائن التنسيق المضمن inputStyle قد تم تعريفه بالفعل بتنسيق افتراضي. هدفنا في هذا التحدي هو تحديث inputStyle بحيث يصبح إطار حقل الإدخال (border) باللون الأحمر السميك (3px solid red) عندما يتجاوز عدد الأحرف المدخلة 15 حرفًا. تجدر الإشارة إلى أن النص في مربع الإدخال يتم حفظه في حالة المكون (component's state) كـ input، كما هو موضح أدناه:

... this.state = {
 input : ''
 }; ...

فهم التحدي: لماذا قد تفشل المحاولة الأولى؟

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

المحاولة الشائعة والخطأ الشائع

تخيل أنك قمت بتضمين الكود التالي لتغيير التنسيق:

 class GateKeeper extends React . Component {
 constructor (props) {
 super (props);
 this .state = {
 input : ''
 };
 this .handleChange = this .handleChange.bind( this );
 }

 handleChange(event) {
 this .setState({
 input : event.target.value
 })
 }

 render() {
 let inputStyle = {
 border : '1px solid black'
 };
 // change code below this line
 const char = 15 ;
 if ( this .state.input > char) {
 inputStyle = {
 border : '3px solid red'
 }
 }
 // change code above this line
 return (
 < div >
 < h3 > Don't Type Too Much: </ h3 >
 < input type = "text" style = {inputStyle} value = {this.state.input} onChange = {this.handleChange} />
 </ div >
 );
 }
 };

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

تحليل مشكلة مقارنة السلاسل النصية

تعريف الثابت char بقيمة 15 أمر صحيح، لكن المشكلة تكمن في شرط if:

 if ( this .state.input > char) {
 inputStyle = {
 border : '3px solid red'
 }
 }

تذكر أن this.state.input هو قيمة مربع الإدخال، وهو عبارة عن سلسلة نصية (string). على سبيل المثال، يمكن أن تكون قيمته "testing testing 1, 2, 3". إذا قمت بإدخال هذه القيمة في مربع النص وقمت بطباعة this.state.input إلى وحدة التحكم (console)، فسترى السلسلة النصية نفسها.

 class GateKeeper extends React . Component {
 constructor (props) {
 super (props);
 this .state = {
 input : ''
 };
 this .handleChange = this .handleChange.bind( this );
 }

 handleChange(event) {
 this .setState({
 input : event.target.value
 })
 }

 render() {
 let inputStyle = {
 border : '1px solid black'
 };
 // change code below this line
 const char = 15 ;
 console .log( this .state.input);
 if ( this .state.input > char) {
 inputStyle = {
 border : '3px solid red'
 }
 }
 // change code above this line
 return (
 < div >
 < h3 > Don't Type Too Much: </ h3 >
 < input type = "text" style = {inputStyle} value = {this.state.input} onChange = {this.handleChange} />
 </ div >
 );
 }
 };

الأهم من ذلك، إذا قمت بطباعة this.state.input > char إلى وحدة التحكم، فسترى أن نتيجتها دائمًا هي false:

 class GateKeeper extends React . Component {
 constructor (props) {
 super (props);
 this .state = {
 input : ''
 };
 this .handleChange = this .handleChange.bind( this );
 }

 handleChange(event) {
 this .setState({
 input : event.target.value
 })
 }

 render() {
 let inputStyle = {
 border : '1px solid black'
 };
 // change code below this line
 const char = 15 ;
 console .log( this .state.input > char);
 if ( this .state.input > char) {
 inputStyle = {
 border : '3px solid red'
 }
 }
 // change code above this line
 return (
 < div >
 < h3 > Don't Type Too Much: </ h3 >
 < input type = "text" style = {inputStyle} value = {this.state.input} onChange = {this.handleChange} />
 </ div >
 );
 }
 };

ببساطة، لا يمكنك مقارنة سلسلة نصية (this.state.input) مباشرة برقم (char). لكي تعمل المقارنة بشكل صحيح، يجب عليك الحصول على طول السلسلة النصية أولاً.

الحلول الفعالة لتغيير CSS الشرطي

1. استخدام جملة if مع خاصية .length

لحل المشكلة، يجب عليك استدعاء الخاصية .length على this.state.input للحصول على طول السلسلة النصية، ثم مقارنة هذا الطول بالعدد المحدد. إليك الكود المصحح:

 class GateKeeper extends React . Component {
 constructor (props) {
 super (props);
 this .state = {
 input : ''
 };
 this .handleChange = this .handleChange.bind( this );
 }

 handleChange(event) {
 this .setState({
 input : event.target.value
 })
 }

 render() {
 let inputStyle = {
 border : '1px solid black'
 };
 // change code below this line
 const char = 15 ;
 if ( this .state.input.length > char) {
 inputStyle = {
 border : '3px solid red'
 }
 }
 // change code above this line
 return (
 < div >
 < h3 > Don't Type Too Much: </ h3 >
 < input type = "text" style = {inputStyle} value = {this.state.input} onChange = {this.handleChange} />
 </ div >
 );
 }
 };

نظرًا لأن طول السلسلة النصية "testing testing 1, 2, 3" هو 23 حرفًا (بما في ذلك المسافات والفواصل)، فإن إطار مربع الإدخال سيتحول إلى اللون الأحمر كما هو متوقع:

صورة توضح حقل إدخال React بإطار أحمر سميك عندما يتجاوز النص 15 حرفًا

2. استخدام عامل التشغيل الثلاثي (Ternary Operator)

عامل التشغيل الثلاثي (Ternary Operator)، أو عامل التشغيل الشرطي، يشبه جملة if...else في سطر واحد، ويمكن أن يساعد في تقصير التعليمات البرمجية بشكل كبير وجعلها أكثر إيجازًا. لنعد إلى الحل الأولي ونزيل كل شيء باستثناء تعريف المتغير char:

 class GateKeeper extends React . Component {
 constructor (props) {
 super (props);
 this .state = {
 input : ''
 };
 this .handleChange = this .handleChange.bind( this );
 }

 handleChange(event) {
 this .setState({
 input : event.target.value
 })
 }

 render() {
 let inputStyle = {
 border : '1px solid black'
 };
 // change code below this line
 // change code above this line
 return (
 < div >
 < h3 > Don't Type Too Much: </ h3 >
 < input type = "text" style = {inputStyle} value = {this.state.input} onChange = {this.handleChange} />
 </ div >
 );
 }
 };

الآن، استخدم الشرط الذي طبقته في جملة if السابقة كجزء أول من الشرط الثلاثي: this.state.input.length > char ? : ;. كل ما بين علامة الاستفهام (?) وعلامة النقطتين (:) يشير إلى ما يحدث إذا كان الشرط صحيحًا. يمكنك ببساطة نسخ الكود الذي كان داخل جملة if سابقًا: this.state.input.length > char ? inputStyle = { border:'3px solid red' } : ;.

بعد ذلك، تحتاج إلى التعامل مع جزء else من عامل التشغيل الثلاثي، وهو كل ما بين علامة النقطتين (:) والفاصلة المنقوطة (;). بينما لم تستخدم جملة else في حلك الأول، فقد استخدمت inputStyle كما هو افتراضيًا. لذا، استخدم inputStyle بالطريقة التي تم تعريفها بها سابقًا في الكود الخاص بك: this.state.input.length > char ? inputStyle = { border:'3px solid red' } : inputStyle;.

يجب أن يبدو الحل الكامل الخاص بك كالتالي:

 class GateKeeper extends React . Component {
 constructor (props) {
 super (props);
 this .state = {
 input : ''
 };
 this .handleChange = this .handleChange.bind( this );
 }

 handleChange(event) {
 this .setState({
 input : event.target.value
 })
 }

 render() {
 let inputStyle = {
 border : '1px solid black'
 };
 // change code below this line
 const char = 15 ;
 this .state.input.length > char ? inputStyle = { border : '3px solid red' } : inputStyle;
 // change code above this line
 return (
 < div >
 < h3 > Don't Type Too Much: </ h3 >
 < input type = "text" style = {inputStyle} value = {this.state.input} onChange = {this.handleChange} />
 </ div >
 );
 }
 };

وهذا كل ما في الأمر! بهذا الحل، ستتمكن من اجتياز التحدي بنجاح وتطبيق التنسيقات الشرطية على مكونات React بفعالية.

الخلاصة التقنية

يُظهر هذا المقال أهمية الفهم الدقيق لأنواع البيانات في JavaScript عند التعامل مع منطق الواجهة الأمامية في React. إن محاولة مقارنة سلسلة نصية برقم مباشرة هي خطأ شائع يمكن تجنبه بسهولة باستخدام خاصية .length. علاوة على ذلك، يوفر عامل التشغيل الثلاثي (Ternary Operator) طريقة أنيقة وموجزة لتطبيق التنسيقات الشرطية، مما يعزز من قابلية قراءة الكود وصيانته. إن إتقان هذه التقنيات يمنح المطورين القدرة على بناء واجهات مستخدم ديناميكية وتفاعلية تستجيب بذكاء لحالة المكون، وهو أمر حيوي لتجربة مستخدم سلسة واحترافية.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *