بداية سريعة
أهلا بك في مستندات react، هذه الصفحة ستعطيك مقدمة ل ٨٠٪ من مفاهيم React التي يتم استخدامها بشكل روتيني في مشاريع React.
You will learn
- كيف تقوم بإنشاء و دمج المكوّنات.
- كيف تضيف تأثيرات على العناصر.
- كيف تقوم بعرض البيانات.
- كيف تستخدم الجمل الشرطية و تعرض عناصر القوائم.
- كيف تتجاوب مع الأحداث المختلفة و تحدث شاشة المستخدم بناءً عليها.
- كيف تشارك البيانات بين أكثر من مكوّن.
إنشاء و دمج المكوّنات
يتم صناعة تطبيقات React اعتمادا على ما يعرف بـ (المكوّنات - Components). المكوّن هو جزء مستقل من واجهة المستخدم و التي لها المنطق البرمجي و الشكل الخاص بها. يمكنك تشكيل المكوّن بالحجم و الشكل المناسب فيتراوح من كونه صغيرا ليمثل (زر) أو كبيرا ليمثل صفحة كاملة. المكوّنات ليست إلا دوال جافاسكريبت و التي توفر (ترميزا مرئيا) كقيمة مرجعة من الدالة.
function MyButton() {
return (
<button>I'm a button</button>
);
}
الآن قمت ببناء مكوّن باسم MyButton
، يمكنك الآن إدخاله في مكون آخر:
export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}
لاحظ كيف أن المكوّن <MyButton />
يبدأ بحرف (كبير) في الإنجليزية (M)، و هي طريقة مستخدمة في React للتمييز و معرفة أن هذه الدالة تمثل مكوّن. أسماء المكوّنات في React يجب أن تبدأ دائما بحرف كبير، بينما يجب أن تكون وسوم ال html المستخدمة بحرف صغير.
خذ نظرة سريعة على النتيجة:
function MyButton() { return ( <button> I'm a button </button> ); } export default function MyApp() { return ( <div> <h1>Welcome to my app</h1> <MyButton /> </div> ); }
عبارة export default
تحدد المكوّن الأساسي في الملف. إذا لم يكن لديك معرفة كافية عن طريقة بناء و كتابة الكود في جافاسكريبت، فيمكنك الرجوع للمصادر التالية:
MDN
javascript.info
بناء الترميز المرئي للواجهة باستخدام JSX
طريقة بناء جمل ترميز الواجهات الذي شاهدته في الأعلى هو ما يسمى بـ jsx. استخدام الـ JSX يعتبر اختياريا، لكن معظم مشاريع React تستخدم الـ JSX لسهولة التعامل معها. كل الأدوات التي ننصح بها لبيئة التطوير تدعم الـ JSX.
تعتبر JSX أكثر صرامة من ال HTML. حيث يجب عليك إغلاق العلامات مثل <br />
. و كذلك فإن المكوّن الذي تقوم بإنشائه لا يمكن أن يرجع لك مجموعة من علامات ال JSX، بل يجب عليك إحاطتهم بأبٍ مشترك مثل: <div>...</div>
أو حتى غطاء <>...</>
الفارغ.
function AboutPage() {
return (
<>
<h1>About</h1>
<p>Hello there.<br />How do you do?</p>
</>
);
}
إذا كان لديك الكثير من الأكواد المكتوبة بال HTML و التي ترغب في تحويلها إلى الـ JSX، فيمكنك استخدام تحويل الـ HTML لـ JSX أون لاين.
إضافة أنماط تصميمية
في React يمكنك تحديد تصنيف باستخدام className
. حيث أنها تعمل تماما كما تعمل خاصية class
في الـ HTML:
<img className="avatar" />
و بعد ذلك يمكنك كتابة قواعد الـ CSS لهذا التصنيف في ملف CSS منفصل:
/* In your CSS */
.avatar {
border-radius: 50%;
}
React لا تحدد لك كيف يجب عليك إضافة ملفات الـ CSS لملف الـ HTML.
ببساطة يمكنك إضافة وسم <link>
لملف الـ html الخاص بك.
إذا كنت تستخدم أداة بناء معينة أو إطار عمل فاستفسر عن طريقة إضافة ملفات الـ CSS لمشروعك من خلال المستندات الخاصة بالأداة.
عرض البيانات
تمكنك الـ JSX من إدخال ترميز الواجهة بداخل الجافاسكريبت، و يمكنك من خلال الأقواس المعقوفة “الخروج” من ترميز الواجهة و العودة مرة أخرى إلى سياق الجافاسكريبت حتى تتمكن من تضمين متغير من أكوادك و عرضه للمستخدم، فمثلا الكود التالي سيُظهر user.name
للمستخدم على الشاشة:
return (
<h1>
{user.name}
</h1>
);
يمكنك كذلك “الخروج إلى سياق الجافاسكريبت” من داخل خواص الـ JSX، لكن يجب عليك حينها استخدام الأقواس المعقوفة بدلا من علامات التنصيص. فمثلا className="avatar"
تقوم بتمرير "avatar"
على أنه التصنيف المستخدم في الـ CSS، و لكن src={user.imageUrl}
تقوم بقراءة قيمة متغير الجافاسكريبت التالي: user.imageUrl
و من ثم تقوم بتمرير قيمته لتمثل خاصية الـ src
:
return (
<img
className="avatar"
src={user.imageUrl}
/>
);
يمكنك كذلك وضع تعبيرات برمجية أكثر تعقيدا بداخل أقواس الـ JSX المعقوفة، مثلا دمج النصوص:
const user = { name: 'Hedy Lamarr', imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg', imageSize: 90, }; export default function Profile() { return ( <> <h1>{user.name}</h1> <img className="avatar" src={user.imageUrl} alt={'Photo of ' + user.name} style={{ width: user.imageSize, height: user.imageSize }} /> </> ); }
في المثال الموضح أعلاه style={{}}
تمثل بناءً خاصا، يحوي بداخله كائن جافاسكريبت المعروف {}
و المعرف بداخل الأقواس المعقوفة الخاصة بال JSX بداخل style={ }
. يمكنك استخدام خاصية style
عندما يكون التصميم لديك معتمدا على متغير جافاسكريبت.
الإظهار الشرطي
في React، لا يوجد طريقة خاصة لكتابة العبارات الشرطية، و إنما يتم استخدام نفس الطرق المستخدمة في كتابة أكواد الجافاسكريبت الاعتيادية، فعلى سبيل المثال يمكنك استخدام عبارة if
لإظهار الـ JSX بشكل شرطي:
let content;
if (isLoggedIn) {
content = <AdminPanel />;
} else {
content = <LoginForm />;
}
return (
<div>
{content}
</div>
);
و إذا كنت تفضل استخدام كود أكثر اختصارا فيمكنك استخدام معامل ?
الشرطي و تتميز بإمكانية استخدامها في داخل ال JSX على النقيض من if
العادية.
<div>
{isLoggedIn ? (
<AdminPanel />
) : (
<LoginForm />
)}
</div>
و في حالة عدم احتياجك لجزئية else
فيمكنك استخدام عبارة &&
المنطقية:
<div>
{isLoggedIn && <AdminPanel />}
</div>
كل الطرق المذكورة في الأعلى يمكن كذلك استخدامها لتحديد قيم الخواص بشكل شرطي. إذا كان هذا النوع من جمل الجافاسكريبت غير مألوفا لديك فيمكنك دائما استخدام عبارة if...else
الاعتيادية.
إظهار القوائم
ستحتاج إلى الاعتماد على ميزات الجافاسكريبت مثل for
loop و كذلك دالة map()
الخاصة بالمصفوفات لإظهار القوائم على المكوّنات.
على سبيل المثال، لنفترض أن لديك مصفوفة لمجموعة من المنتجات كالتالي:
const products = [
{ title: 'Cabbage', id: 1 },
{ title: 'Garlic', id: 2 },
{ title: 'Apple', id: 3 },
];
قم باستخدام دالة map()
بداخل المكوّن الخاص بك لتحويل مصفوفة المنتجات إلى مصفوفة من عناصر الـ <li>
:
const listItems = products.map(product =>
<li key={product.id}>
{product.title}
</li>
);
return (
<ul>{listItems}</ul>
);
لاحظ أن كل <li>
لديه خاصية باسم key
. كل عنصر في أي قائمة يجب أن يتم تمرير رقم أو سلسلة نصية إليه لتميّزه عن كل العناصر الأخرى الموجودة في نفس القائمة. هذه الخاصية عادة ما يتم تعبئتها من صلب البيانات الخاصة بمشروعك مثل الـ ID الخاص بقاعدة البيانات. هذا المفتاح (key) يتم استخدامه من React ولمعرفة ما الذي حدث تحديدا في حال قمت لاحقا بإضافة، حذف أو إعادة ترتيب لعناصر القائمة.
const products = [ { title: 'Cabbage', isFruit: false, id: 1 }, { title: 'Garlic', isFruit: false, id: 2 }, { title: 'Apple', isFruit: true, id: 3 }, ]; export default function ShoppingList() { const listItems = products.map(product => <li key={product.id} style={{ color: product.isFruit ? 'magenta' : 'darkgreen' }} > {product.title} </li> ); return ( <ul>{listItems}</ul> ); }
الاستجابة للأحداث
يمكنك الاستجابة للأحداث عن طريق تعريف ما يعرف بدوال (معالج الحدث) أو الـ event handler بداخل المكوّن الخاص بك:
function MyButton() {
function handleClick() {
alert('You clicked me!');
}
return (
<button onClick={handleClick}>
Click me
</button>
);
}
لاحظ أن onClick={handleClick}
لا تحتوي على أقواس الاستدعاء في النهاية! لا تقم باستدعاء معالج الحدث، يكفيك أن تقوم بتمرير اسمها فقط. حيث أن React ستقوم باستدعاء دالة معالجة الحدث عندما يقوم المستخدم بالضغط على الزر.
تحديث الشاشة
غالبا ستكون بحاجة أن يقوم المكوّن “بتذكر” المعلومات و عرضها على الشاشة. فمثلا، قد تحتاج إلى عرض عدد المرات التي تم فيها الضغط على زر ما. لتنفيذ ذلك قم بإضافة ما يعرف ب حالة أو الـ state الخاصة بالمكون:
في البداية، قم باستيراد useState
من React:
import { useState } from 'react';
و الآن يمكنك تعريف متغير الحالة أو الـ state variable بداخل المكوّن:
function MyButton() {
const [count, setCount] = useState(0);
// ...
ستحصل على شيئين من دالة useState
: الحالة الحالية (count
)، و كذلك الدالة التي تمكنك من تحديث القيمة (setCount
). يمكنك تسميتهما ما تشاء، و لكن المتعارف عليه أن يتم تسميتها بالشكل التالي: [something, setSomething]
.
في المرة الأولى التي يظهر فيها الزر ستكون قيمة coount
تساوي 0
و ذلك لأنك قمت بتمرير 0
كبارامتر لدالة useState()
. عندما تريد تغيير الحالة، قم باستدعاء setCount()
و تمرير القيمة الجديدة لها. و بالتالي فإن الضغط على هذا الزر سيزيد العداد count
.
function MyButton() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}
الآن ستقوم React باستدعاء المكوّن الخاص بك مجددا. في هذه المرة قيمة count
ستكون 1
، و من ثم ستكون 2
، و هكذا.
إذا قمت بإظهار المكوّن عدة مرات فإن كل مرة ستكون لها الحالة المستقلة الخاصة بها. قم بتجربة الضغط على كل زر على حدة:
import { useState } from 'react'; export default function MyApp() { return ( <div> <h1>Counters that update separately</h1> <MyButton /> <MyButton /> </div> ); } function MyButton() { const [count, setCount] = useState(0); function handleClick() { setCount(count + 1); } return ( <button onClick={handleClick}> Clicked {count} times </button> ); }
لاحظ كيف أن كل زر قادر على “تذكر” حالة الـ count
الخاصة به دون أي تعارض مع حالة الزر الآخر.
استخدام الخطافات
الدوال التي تبدأ بـ use
تسمى الخطافات أو Hooks. تعتبر useState
أحد الخطافات المجهّزة و التي توفرها React. و بإمكانك العثور على قائمة الخطافات المختلفة التي توفرها React في API reference. ، يمكنك كذلك كتابة الخطافات الخاصة بك عن طريق الجمع بين الخطافات الجاهزة و الموفّرة من React.
الخطافات أكثر صرامة من الدوال الأخرى. يمكنك استدعاء الخطاف في مقدمة المكوّن (أو في مقدمة أي خطاف آخر). إذا أردت استخدام useState
في عبارة شرطية أو في حملة تكرار فقم ببناء مكوّن مستقل و من ثم استخدامها هناك.
مشاركة البيانات بين المكوّنات
في المثال السابق، كل MyButton
كان لديه حالة الـ count
المستقلة الخاصة به، و عندما يتم الضغط على أي منهما حينها يتم تعديل الـ count
الخاصة بذلك الزر فقط:
مبدئيا، حالة count
الخاصة بكل زر تساوي 0
مكوّن MyButton
الأول سيقوم بتحديث حالة الـ count
الخاصة به إلى 1
و بالرغم من ذلك، فإنك غالبا ستحتاج أن تقوم المكوّنات بـ ،مشاركة البيانات و أن يتم تحديثها معا
و لجعل كلا المكونين MyButton
يقومان بعرض نفس الـ count
و يتم تحديثهما معا فسنحتاج إلى نقل الحالة من كل زر بشكل مستقل “إلى الأعلى” لأقرب مكوّن يحوي كلا المكوّنين.
في هذا المثال MyApp
يمثل هذا هذا المكون الأب الذي يحوي كل المكونين:
في البداية حالة الـ count
الخاصة بال MyApp
تساوي 0
، و يتم تمريرها للأسفل لكلا الإبنين.
عند الضغط على أي من الزرين سيقوم ال MyApp
بتحديث حالة الـ count
الخاصة به إلى 1
و من ثم يمرر القيمة إلى الأسفل لكلا الإبنين
و الآن عند الضغط على أي من الزرين، فإن الـ count
في MyApp
ستتغير، و بالتالي سيغير ذلك بدوره كلا العدادين المتواجدين في MyButton
. يمكنك تمثيل ذلك بالكود كالتالي:
في البداية قم بنقل الحالة للأعلى من MyButton
إلى MyApp
:
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>Counters that update separately</h1>
<MyButton />
<MyButton />
</div>
);
}
function MyButton() {
// ... we're moving code from here ...
}
و من ثم قم بتمرير الحالة للأسفل من MyApp
لكلا مكوّني الـ MyButton
بالإضافة إلى دالة معالجة الضغط على الزر (click handler). بإمكانك إسال معلومات إلى MyButton
باستخدام أقواس الـ JSX المعقوفة، تماما كما فعلت سابقا في الأوسمة الجاهزة مثل وسم <img>
:
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>Counters that update together</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}
هذه المعلومات التي تقوم بتمريرها للأسفل تسمى props أو خواص المكوّن. و الآن مكون MyApp
يحتوي على حالة الـ count
بالإضافة لمعالج الحدث باسم handleClick
، و يقوم بإرسالهما للأسفل لكلا الزرين.
أخيرا قم بتغيير كود MyButton
ليقوم بـ قراءة خواص المكوّن التي قمت بتمريرها إليه من مكوّن الأب:
function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
Clicked {count} times
</button>
);
}
عندما تقوم بالضغط على الزر سيتم تشغيل معالج الحدث الذي يحمل اسم onClick
. خاصية معالجة الحدث المرسلة لكلا الزرين و التي تحمل اسم onClick
في كليهما هي في حقيقة الأمر تمثل دالة الـ handleClick
المعرّفة بداخل الـ MyApp
، و بالتالي سيتم تنفيذ الكود المعرّف بداخلها. ذلك الكود سيقوم باستدعاء setCount(count + 1)
، و الذي بدوره سيزيد حالة الـ count
. و من ثم فإن القيمة الجديدة للـ count
سيتم تمريرها لكلي الزرين و بالتالي فإن كليهما سيُظهران نفس القيمة. هذا ما يعرف بـ “نقل الحالة للأعلى”. بنقلك للحالة للأعلى تكون قد جعلت الحالة مشتركة بين المكوّنات.
import { useState } from 'react'; export default function MyApp() { const [count, setCount] = useState(0); function handleClick() { setCount(count + 1); } return ( <div> <h1>Counters that update together</h1> <MyButton count={count} onClick={handleClick} /> <MyButton count={count} onClick={handleClick} /> </div> ); } function MyButton({ count, onClick }) { return ( <button onClick={onClick}> Clicked {count} times </button> ); }
الخطوات القادمة
و الآن أنت تعرف أساسيات بناء كود React! اطّلع على هذا الدرس لتفعيل هذه الأساسيات بشكل عملي و بناء مشروعك المصغّر الأوّل باستخدام React.