تحديث النصوص والأرقام بشكل تفاعلي باستخدام خطاف useState


ماذا سنتعلم اليوم؟

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

ملاحظة تقنية: خطاف useState هو وظيفة خاصة توفرها React تتيح للمكونات الوظيفية (Functional Components) "تذكر" المعلومات. إنه الطريقة الأساسية لإضافة "حالة" (state) إلى مكونات React الوظيفية.

الخطوة 1: إعداد المكون الأساسي واستيراد useState

سنبدأ بإنشاء مكون React وظيفي بسيط واستيراد خطاف useState منه. افترض أنك قمت بإنشاء مشروع React جديد باستخدام npx create-react-app my-app.

// src/App.js
import React, { useState } from 'react'; // استيراد React وخطاف useState

function App() {
  // هنا سنقوم بتعريف حالاتنا لاحقاً
  return (
    <div style={{ textAlign: 'center', padding: '20px' }}>
      <h1>درس useState التفاعلي</h1>
      {/* هنا سيظهر المحتوى التفاعلي */}
    </div>
  );
}

export default App;

في هذا الجزء، قمنا باستيراد useState من مكتبة React. المكون App هو نقطة البداية لتطبيقنا.

الخطوة 2: تحديث النصوص باستخدام useState

الآن، لنقم بتعريف حالة (state) لتخزين نص، ونعرض هذا النص، ثم نوفر حقل إدخال لتحديثه بشكل تفاعلي.

// src/App.js (الجزء المضاف أو المعدل)
import React, { useState } from 'react';

function App() {
  // تعريف حالة النص الابتدائية 'مرحباً React!'
  // 'currentText' هو المتغير الذي يحمل القيمة الحالية
  // 'setCurrentText' هي الدالة التي نستخدمها لتحديث القيمة
  const [currentText, setCurrentText] = useState('مرحباً React!');

  // دالة لمعالجة التغييرات في حقل الإدخال
  const handleTextChange = (event) => {
    // تحديث قيمة النص باستخدام الدالة 'setCurrentText'
    setCurrentText(event.target.value);
  };

  return (
    <div style={{ textAlign: 'center', padding: '20px' }}>
      <h1>درس useState التفاعلي</h1>
      <h3>تحديث النصوص</h3>
      <p>النص الحالي: <strong>{currentText}</strong></p> {/* عرض النص الحالي */}
      <input
        type="text"
        value={currentText} // ربط قيمة حقل الإدخال بحالة النص
        onChange={handleTextChange} // استدعاء الدالة عند كل تغيير في الإدخال
        style={{ padding: '8px', width: '300px', marginBottom: '15px' }}
        placeholder="اكتب شيئاً هنا..."
      />
    </div>
  );
}

export default App;

هنا، استخدمنا useState('مرحباً React!') لإنشاء متغير حالة currentText ودالة لتحديثه setCurrentText. كلما كتب المستخدم شيئاً في حقل الإدخال، يتم استدعاء handleTextChange التي تقوم بتحديث currentText، مما يؤدي إلى إعادة عرض المكون بالقيمة الجديدة.

الخطوة 3: تحديث الأرقام بشكل تفاعلي

لنضيف الآن عداداً رقمياً يمكن زيادته أو إنقاصه باستخدام الأزرار، وذلك باستخدام حالة useState أخرى.

// src/App.js (الجزء المضاف أو المعدل)
import React, { useState } from 'react';

function App() {
  // حالة النص (من الخطوة السابقة)
  const [currentText, setCurrentText] = useState('مرحباً React!');
  const handleTextChange = (event) => {
    setCurrentText(event.target.value);
  };

  // تعريف حالة العداد الابتدائية 0
  const [count, setCount] = useState(0);

  // دالة لزيادة العداد
  const incrementCount = () => {
    setCount(prevCount => prevCount + 1); // تحديث العداد بزيادة قيمته السابقة بـ 1
  };

  // دالة لإنقاص العداد
  const decrementCount = () => {
    setCount(prevCount => prevCount - 1); // تحديث العداد بإنقاص قيمته السابقة بـ 1
  };

  return (
    <div style={{ textAlign: 'center', padding: '20px' }}>
      <h1>درس useState التفاعلي</h1>

      {/* قسم تحديث النصوص */}
      <h3>تحديث النصوص</h3>
      <p>النص الحالي: <strong>{currentText}</strong></p>
      <input
        type="text"
        value={currentText}
        onChange={handleTextChange}
        style={{ padding: '8px', width: '300px', marginBottom: '15px' }}
        placeholder="اكتب شيئاً هنا..."
      />

      <hr style={{ margin: '30px auto', width: '50%' }} /> {/* فاصل */}

      {/* قسم تحديث الأرقام */}
      <h3>تحديث الأرقام (العداد)</h3>
      <p>العداد الحالي: <strong>{count}</strong></p> {/* عرض قيمة العداد */}
      <button
        onClick={decrementCount} // استدعاء دالة الإنقاص عند النقر
        style={{ padding: '10px 20px', margin: '5px', fontSize: '16px', cursor: 'pointer' }}
      >
        إنقاص
      </button>
      <button
        onClick={incrementCount} // استدعاء دالة الزيادة عند النقر
        style={{ padding: '10px 20px', margin: '5px', fontSize: '16px', cursor: 'pointer' }}
      >
        زيادة
      </button>
    </div>
  );
}

export default App;

في هذا الجزء، أضفنا حالة count ودالتها setCount. استخدمنا دالتين incrementCount و decrementCount لتغيير قيمة العداد. لاحظ أننا استخدمنا prevCount => prevCount + 1 عند تحديث الحالة. هذه هي الطريقة المفضلة لتحديث الحالة عندما تعتمد القيمة الجديدة على القيمة السابقة، لضمان الحصول على أحدث قيمة للحالة.

الكود النهائي الكامل

هذا هو الكود الكامل لملف src/App.js الذي يجمع بين تحديث النصوص والأرقام:

import React, { useState } from 'react'; // استيراد React وخطاف useState

function App() {
  // 1. تعريف حالة النص الابتدائية 'مرحباً React!'
  // 'currentText' هو المتغير الذي يحمل القيمة الحالية
  // 'setCurrentText' هي الدالة التي نستخدمها لتحديث القيمة
  const [currentText, setCurrentText] = useState('مرحباً React!');

  // دالة لمعالجة التغييرات في حقل إدخال النص
  const handleTextChange = (event) => {
    // تحديث قيمة النص باستخدام الدالة 'setCurrentText'
    setCurrentText(event.target.value);
  };

  // 2. تعريف حالة العداد الابتدائية 0
  // 'count' هو المتغير الذي يحمل القيمة الرقمية الحالية
  // 'setCount' هي الدالة التي نستخدمها لتحديث قيمة العداد
  const [count, setCount] = useState(0);

  // دالة لزيادة العداد
  const incrementCount = () => {
    // تحديث العداد بزيادة قيمته السابقة بـ 1
    // استخدام دالة رد الاتصال يضمن أننا نعمل بأحدث قيمة للحالة
    setCount(prevCount => prevCount + 1);
  };

  // دالة لإنقاص العداد
  const decrementCount = () => {
    // تحديث العداد بإنقاص قيمته السابقة بـ 1
    setCount(prevCount => prevCount - 1);
  };

  return (
    <div style={{ textAlign: 'center', padding: '20px', fontFamily: 'Arial, sans-serif' }}>
      <h1>درس useState التفاعلي</h1>

      {/* قسم تحديث النصوص */}
      <h3>تحديث النصوص</h3>
      <p>النص الحالي: <strong>{currentText}</strong></p> {/* عرض النص الحالي */}
      <input
        type="text"
        value={currentText} // ربط قيمة حقل الإدخال بحالة النص
        onChange={handleTextChange} // استدعاء الدالة عند كل تغيير في الإدخال
        style={{ padding: '8px', width: '300px', marginBottom: '15px', borderRadius: '4px', border: '1px solid #ccc' }}
        placeholder="اكتب شيئاً هنا..."
      />

      <hr style={{ margin: '30px auto', width: '50%', borderTop: '1px solid #eee' }} /> {/* فاصل بصري */}

      {/* قسم تحديث الأرقام */}
      <h3>تحديث الأرقام (العداد)</h3>
      <p>العداد الحالي: <strong>{count}</strong></p> {/* عرض قيمة العداد */}
      <button
        onClick={decrementCount} // استدعاء دالة الإنقاص عند النقر
        style={{ padding: '10px 20px', margin: '5px', fontSize: '16px', cursor: 'pointer', backgroundColor: '#dc3545', color: 'white', border: 'none', borderRadius: '5px' }}
      >
        إنقاص
      </button>
      <button
        onClick={incrementCount} // استدعاء دالة الزيادة عند النقر
        style={{ padding: '10px 20px', margin: '5px', fontSize: '16px', cursor: 'pointer', backgroundColor: '#28a745', color: 'white', border: 'none', borderRadius: '5px' }}
      >
        زيادة
      </button>
    </div>
  );
}

export default App;

النتيجة المتوقعة

عند تشغيل التطبيق (باستخدام npm start في مجلد المشروع)، ستظهر لك صفحة ويب تحتوي على عنوان ومكونين رئيسيين:

  1. قسم تحديث النصوص: سيظهر حقل إدخال ونص "النص الحالي: مرحباً React!". عند الكتابة في حقل الإدخال، سيتغير النص المعروض فوراً ليعكس ما تكتبه.
  2. قسم تحديث الأرقام (العداد): سيظهر نص "العداد الحالي: 0" وزرين، "إنقاص" و "زيادة". عند النقر على زر "زيادة"، سيزداد الرقم المعروض بمقدار واحد. وعند النقر على زر "إنقاص"، سينقص الرقم بمقدار واحد.

يوضح هذا الدرس بوضوح كيف يمكن لـ useState أن يجعل مكوناتك تتفاعل مع المستخدم وتتغير ديناميكياً بناءً على مدخلاته.