React

المكونات في React — دليل شامل Components 2026

📅 2026-10-12⏱ 9 دقائق قراءة
في المقال السابق، كتبت أول تطبيق React واستخدمت JSX والمكونات. الآن سنتعمق في **المكونات (Components)** — وهي **قلب React** وأساس كل تطبيق. في هذا الدليل العملي، سنأخذك خطوة بخطوة لفهم المكونات، وأنواعها، وكيفية تركيبها، مع تمارين وحلول. ## ما هي المكوّنة (Component)؟ المكوّنة هي **قطعة مستقلة** من واجهة المستخدم، لها منطقها الخاص، ويمكن إعادة استخدامها. **تشبيه بسيط:** تخيل أن موقعك **سيارة**. المكونات هي **القطع**: - المحرك (مكوّن). - العجلات (مكوّن). - المقود (مكوّن). - الأبواب (مكوّن). كل قطعة **مستقلة**، لكنها **تعمل معاً** لتشكيل السيارة. ## لماذا نحتاج المكونات؟ - **إعادة الاستخدام:** اكتب مرة، استخدم في كل مكان. - **التنظيم:** كود مرتب وسهل الصيانة. - **الاختبار:** اختبار كل مكوّنة على حدة. - **التعاون:** فريق العمل يقسّم المهام. - **الأداء:** React يحدّث فقط المكونات المتغيرة. ## أنواع المكونات ### 1. Function Components (الطريقة الحديثة) ```tsx function Welcome() { return <h1>مرحباً!</h1>; } export default Welcome; ``` **ميزاتها:** - ✅ أبسط وأقصر. - ✅ يمكن استخدام Hooks (`useState`, `useEffect`). - ✅ الطريقة الموصى بها حالياً. ### 2. Arrow Function Components ```tsx const Welcome = () => { return <h1>مرحباً!</h1>; }; export default Welcome; ``` **أو أقصر:** ```tsx const Welcome = () => <h1>مرحباً!</h1>; export default Welcome; ``` ### 3. Class Components (الطريقة القديمة) ```tsx import { Component } from "react"; class Welcome extends Component { render() { return <h1>مرحباً!</h1>; } } export default Welcome; ``` **⚠️ تحذير:** **لا تستخدم Class Components** في المشاريع الجديدة. استخدم Function Components. ## إنشاء مكونات ### 1. مكوّنة بسيطة **أنشئ `src/components/Header.tsx`:** ```tsx function Header() { return ( <header className="header"> <h1>موقعي</h1> <nav> <a href="/">الرئيسية</a> <a href="/about">من نحن</a> </nav> </header> ); } export default Header; ``` ### 2. استخدامها في `App.tsx` ```tsx import Header from "./components/Header"; function App() { return ( <div> <Header /> </div> ); } export default App; ``` ## Props — تمرير البيانات **Props** هي **بيانات** تُمرر من المكوّن الأب إلى المكوّن الابن. ### 1. Props مع TypeScript ```tsx interface GreetingProps { name: string; age: number; } function Greeting({ name, age }: GreetingProps) { return ( <div> <h2>مرحباً {name}!</h2> <p>عمرك {age} سنة</p> </div> ); } export default Greeting; ``` ### 2. استخدام Props ```tsx <Greeting name="أحمد" age={25} /> <Greeting name="محمد" age={30} /> ``` **⚠️ ملاحظة:** النصوص `"..."`، الأرقام `{...}`. ### 3. Props مع قيم افتراضية ```tsx interface ButtonProps { text?: string; color?: string; onClick?: () => void; } function Button({ text = "اضغط", color = "blue", onClick, }: ButtonProps) { return ( <button onClick={onClick} style={{ backgroundColor: color, color: "white", padding: "10px 20px", border: "none", borderRadius: "8px", cursor: "pointer" }} > {text} </button> ); } ``` ### 4. تمرير المكونات كـ Children ```tsx interface CardProps { title: string; children: React.ReactNode; } function Card({ title, children }: CardProps) { return ( <div className="card"> <h3>{title}</h3> <div className="card-body">{children}</div> </div> ); } ``` **الاستخدام:** ```tsx <Card title="معلومات"> <p>هذا محتوى البطاقة</p> <p>يمكن أن يكون أي شيء</p> </Card> ``` ## تركيب المكونات (Composition) **التركيب** هو دمج مكونات صغيرة لبناء مكونات أكبر. ### 1. مكونات صغيرة ```tsx // src/components/Title.tsx function Title({ children }: { children: React.ReactNode }) { return <h2 className="title">{children}</h2>; } // src/components/Paragraph.tsx function Paragraph({ children }: { children: React.ReactNode }) { return <p className="paragraph">{children}</p>; } ``` ### 2. مكوّنة كبيرة تجمعها ```tsx // src/components/Article.tsx import Title from "./Title"; import Paragraph from "./Paragraph"; interface ArticleProps { title: string; content: string; } function Article({ title, content }: ArticleProps) { return ( <article> <Title>{title}</Title> <Paragraph>{content}</Paragraph> </article> ); } ``` ### 3. استخدام `Article` في `App.tsx` ```tsx import Article from "./components/Article"; function App() { return ( <div> <Article title="تعلم React" content="React مكتبة رائعة لبناء واجهات المستخدم." /> <Article title="تعلم TypeScript" content="TypeScript يضيف أنواع البيانات لـ JavaScript." /> </div> ); } ``` ## إنشاء تطبيق "مدونة صغيرة" دعنا نبني تطبيقاً كاملاً يجمع كل المفاهيم. ### 1. مكوّنة `Post.tsx` ```tsx interface PostProps { title: string; content: string; author: string; date: string; } function Post({ title, content, author, date }: PostProps) { return ( <article className="post"> <h2>{title}</h2> <div className="meta"> <span>✍️ {author}</span> <span>📅 {date}</span> </div> <p>{content}</p> </article> ); } export default Post; ``` ### 2. مكوّنة `Blog.tsx` ```tsx import Post from "./Post"; const posts = [ { title: "أساسيات React", content: "React هي مكتبة JavaScript لبناء واجهات المستخدم.", author: "أحمد", date: "2026-10-12", }, { title: "مقدمة في TypeScript", content: "TypeScript تضيف أنواع البيانات لـ JavaScript.", author: "محمد", date: "2026-10-11", }, { title: "بناء تطبيقات Next.js", content: "Next.js هو إطار عمل مبني على React.", author: "علي", date: "2026-10-10", }, ]; function Blog() { return ( <div className="blog"> <h1>📝 مدونتي</h1> {posts.map((post) => ( <Post key={post.title} title={post.title} content={post.content} author={post.author} date={post.date} /> ))} </div> ); } export default Blog; ``` ### 3. `App.tsx` ```tsx import Blog from "./components/Blog"; function App() { return <Blog />; } export default App; ``` ### 4. تصميم `index.css` ```css body { font-family: 'Segoe UI', sans-serif; background: #f1f5f9; direction: rtl; padding: 40px 20px; } .blog { max-width: 800px; margin: 0 auto; } .blog h1 { color: #1e293b; margin-bottom: 24px; text-align: center; } .post { background: white; padding: 24px; border-radius: 16px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); margin-bottom: 16px; } .post h2 { color: #1e293b; margin-bottom: 8px; } .post .meta { display: flex; gap: 16px; color: #64748b; font-size: 14px; margin-bottom: 12px; } .post p { color: #334155; line-height: 1.7; } ``` **🎉 مبروك! لديك تطبيق مدونة كامل!** ## الأنماط الشائعة ### 1. مكوّنة في ملف واحد ``` src/components/Button.tsx ``` ### 2. عدة مكونات في ملف واحد ``` src/components/Button.tsx (يحتوي على Button, IconButton, ...) ``` ### 3. مجلد لكل مكوّنة ``` src/components/Button/ ├── Button.tsx ├── Button.css └── index.ts (لتصدير Button) ``` ### 4. تنظيم حسب الميزة ``` src/features/ ├── auth/ │ ├── LoginForm.tsx │ └── RegisterForm.tsx └── posts/ ├── PostList.tsx └── PostItem.tsx ``` ## Props Drilling — المشكلة والحل **Props Drilling** هو تمرير Props عبر طبقات كثيرة. **مثال:** ```tsx // App → Layout → Header → UserMenu → Avatar <Avatar user={user} /> // يمرر عبر 4 طبقات ``` **⚠️ المشكلة:** كل مكوّنة في الطريق تحتاج تمرير Props. **✅ الحل:** استخدم **Context API** (سنتعلمه في مقال لاحق). ## PropTypes vs TypeScript **PropTypes** كانت الطريقة القديمة (JavaScript): ```jsx import PropTypes from 'prop-types'; function Greeting({ name }) { return <h1>مرحباً {name}</h1>; } Greeting.propTypes = { name: PropTypes.string.isRequired, }; ``` **TypeScript** هي الطريقة الحديثة: ```tsx interface GreetingProps { name: string; } function Greeting({ name }: GreetingProps) { return <h1>مرحباً {name}</h1>; } ``` **✅ استخدم TypeScript** — أفضل وأنظف. ## أفضل الممارسات ### 1. أسماء المكونات تبدأ بحرف كبير ```tsx <Button /> // ✅ <button /> // ❌ (عنصر HTML) ``` ### 2. مكوّنة واحدة لكل ملف ``` Button.tsx → مكونة Button Card.tsx → مكونة Card ``` ### 3. Props واضحة ```tsx interface ButtonProps { text: string; onClick: () => void; variant?: "primary" | "secondary"; } ``` ### 4. تجنب المكونات الكبيرة جداً **إذا كان المكوّن أكبر من 200 سطر → قسّمه.** ### 5. استخدم أسماء وصفية ```tsx ✅ <UserProfileCard /> ❌ <Card1 /> ``` ## تمارين عملية ### تمرين 1: مكوّنة Button أنشئ مكوّنة `Button` تقبل `text` و `onClick`. **الحل:** ```tsx interface ButtonProps { text: string; onClick: () => void; } function Button({ text, onClick }: ButtonProps) { return ( <button onClick={onClick} className="btn"> {text} </button> ); } ``` ### تمرين 2: مكوّنة Product أنشئ مكوّنة `Product` تقبل `name`, `price`, `image`. **الحل:** ```tsx interface ProductProps { name: string; price: number; image: string; } function Product({ name, price, image }: ProductProps) { return ( <div className="product"> <img src={image} alt={name} /> <h3>{name}</h3> <p>{price} $</p> </div> ); } ``` ### تمرين 3: مكوّنة Alert أنشئ مكوّنة `Alert` تقبل `type` (success/error/warning) و `message`. **الحل:** ```tsx interface AlertProps { type: "success" | "error" | "warning"; message: string; } function Alert({ type, message }: AlertProps) { const colors = { success: "#10b981", error: "#ef4444", warning: "#f59e0b", }; return ( <div style={{ padding: "12px 16px", borderRadius: "8px", backgroundColor: colors[type] + "20", color: colors[type], border: `2px solid ${colors[type]}`, }} > {message} </div> ); } ``` ### تمرين 4: مكوّنة Avatar أنشئ مكوّنة `Avatar` تقبل `name` و `src` اختياري. **الحل:** ```tsx interface AvatarProps { name: string; src?: string; } function Avatar({ name, src }: AvatarProps) { if (src) { return <img src={src} alt={name} className="avatar" />; } return ( <div className="avatar-fallback"> {name.charAt(0).toUpperCase()} </div> ); } ``` ### تمرين 5: مكوّنة Card مع Children أنشئ مكوّنة `Card` تقبل `children` و `title`. **الحل:** ```tsx interface CardProps { title: string; children: React.ReactNode; } function Card({ title, children }: CardProps) { return ( <div className="card"> <h3>{title}</h3> <div>{children}</div> </div> ); } ``` ### تمرين 6: مكوّنة List عامة أنشئ مكوّنة `List` تقبل مصفوفة `items` ودالة `renderItem`. **الحل:** ```tsx interface ListProps<T> { items: T[]; renderItem: (item: T) => React.ReactNode; } function List<T>({ items, renderItem }: ListProps<T>) { return <ul>{items.map((item, i) => <li key={i}>{renderItem(item)}</li>)}</ul>; } // الاستخدام: <List items={["أحمد", "محمد"]} renderItem={(name) => <strong>{name}</strong>} /> ``` ## حل المشاكل الشائعة ### 🔴 المشكلة 1: `Component is not defined` **السبب:** لم تستورد المكوّنة. **الحل:** ```tsx import MyComponent from "./MyComponent"; ``` ### 🔴 المشكلة 2: `Type 'X' is not assignable to type 'Y'` **السبب:** Props بنوع خاطئ. **الحل:** تحقق من الـ interface. ### 🔴 المشكلة 3: المكوّنة لا تظهر **السبب:** لم تُرجع JSX. **الحل:** ```tsx function MyComponent() { return <div>محتوى</div>; // ← يجب أن يكون هناك return } ``` ### 🔴 المشكلة 4: `key` مفقود في القائمة **الحل:** أضف `key` فريد. ## جدول مقارنة: <table> <thead> <tr> <th>النوع</th> <th>Function</th> <th>Class</th> </tr> </thead> <tbody> <tr> <td><strong>الصيغة</strong></td> <td><code>function Fn() {}</code></td> <td><code>class Fn extends Component</code></td> </tr> <tr> <td><strong>State</strong></td> <td>✅ Hooks</td> <td>⚠️ this.state</td> </tr> <tr> <td><strong>الحجم</strong></td> <td>🪶 صغير</td> <td>📦 كبير</td> </tr> <tr> <td><strong>الحداثة</strong></td> <td>✅ حديث</td> <td>⚠️ قديم</td> </tr> <tr> <td><strong>الاستخدام</strong></td> <td>✅ موصى به</td> <td>❌ تجنبه</td> </tr> </tbody> </table> ## قائمة تحقق نهائية <table> <thead> <tr> <th>المهمة</th> <th>الحالة</th> </tr> </thead> <tbody> <tr> <td>فهم أنواع المكونات</td> <td>⬜</td> </tr> <tr> <td>إنشاء مكونات بسيطة</td> <td>⬜</td> </tr> <tr> <td>استخدام Props</td> <td>⬜</td> </tr> <tr> <td>تمرير Children</td> <td>⬜</td> </tr> <tr> <td>تركيب المكونات</td> <td>⬜</td> </tr> <tr> <td>بناء تطبيق المدونة</td> <td>⬜</td> </tr> <tr> <td>حل التمارين الستة</td> <td>⬜</td> </tr> </tbody> </table> ## ماذا بعد هذا المقال؟ الآن بعد أن أتقنت المكونات، أنت جاهز للمقال التالي: 1. **State** — إدارة البيانات المتغيرة. 2. **الأحداث** — التعامل مع تفاعل المستخدم. 3. **useEffect** — التأثيرات الجانبية. ## الخلاصة في هذا المقال، تعلمت: - ✅ ما هي المكونات ولماذا نحتاجها. - ✅ أنواع المكونات (Function, Class). - ✅ Props وكيفية تمريرها. - ✅ Children وتركيب المكونات. - ✅ أفضل ممارسات تنظيم المكونات. - ✅ Props Drilling ومشكلته. - ✅ حل 6 تمارين عملية. **تذكر:** المكونات هي أساس React. أتقنها جيداً، وستتمكن من بناء أي تطبيق. **هل أتقنت المكونات؟ شاركنا في التعليقات!**