React: إعداد البيئة و JSX
آخر تحديث: 2026-08-26
كتابة كود React تشبه تجديد منزل — Vite هي فريق البناء (فهي تساعدك في إعداد السقالات وخادم التطوير)، وJSX هي المخطط (وهي صيغة لكتابة HTML داخل JavaScript). في هذا الدرس، ستقوم بإنشاء أول مشروع React خاص بك من الصفر.
1. ما ستتعلمه
- إنشاء مشروع React بسرعة باستخدام Vite
- هيكل دليل المشروع والغرض من كل ملف
- قواعد صياغة JSX (التعبيرات، الشروط، القوائم)
- الاختلافات الرئيسية بين JSX و HTML
- تثبيت واستخدام React DevTools
2. قصة حقيقية لمطور مبتدئ
(1) المشكلة: استغرق إعداد البيئة يومًا كاملاً
لقد تعلم بوب لغة جافا سكريبت مؤخرًا ويرغب في تجربة React. بحث على الإنترنت عن دروس تعليمية، فوجد أن البعض أوصى باستخدام Create React App، بينما أوصى آخرون باستخدام Vite، وأوصى آخرون باستخدام Next.js. فاختار CRA عشوائيًا وبدأ عملية التثبيت:
npx create-react-app my-app
النتائج:
- استغرق التثبيت 8 دقائق (مع تنزيل أكثر من 200 ميغابايت من المكونات التبعية)
- استغرق تشغيل خادم التطوير 30 ثانية
- يحتوي دليل المشروع على أكثر من 35,000 ملف (node_modules)
- يؤدي تغيير سطر واحد من التعليمات البرمجية إلى أن تستغرق الصفحة 2–3 ثوانٍ لتتحديث
شعر بوب بالإحباط: «لم أبدأ حتى في كتابة الكود، وقد أهدرت ساعة بالفعل».
(2) الحل باستخدام Vite و React
إنشاء نفس المشروع باستخدام Vite:
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
npm run dev
| المقارنة | CRA | Vite |
|---|---|---|
| مدة التثبيت | ~8 دقائق | ~30 ثانية |
| وقت بدء التشغيل | ~30 ثانية | < 1 ثانية |
| استبدال الوحدة الساخنة (HMR) | 2–3 ثوانٍ | <50 مللي ثانية |
| وقت البناء | ~60 ثانية | ~10 ثوانٍ |
| حجم node_modules | ~200 ميغابايت | ~80 ميغابايت |
المزايا: لم يستغرق الأمر من بوب سوى 3 دقائق من لحظة التثبيت حتى ظهور عبارة "Hello World"، كما أن التحديثات الفورية سريعة للغاية لدرجة أنك بالكاد تلاحظ فترة الانتظار.
3. القواعد الأساسية لـ JSX
JSX هي اختصار لـ JavaScript XML. وهي ليست HTML، بل هي امتداد لصيغة لغة JavaScript. ويتم ترجمة كل تعبير JSX في النهاية إلى استدعاء React.createElement().
graph LR
A[JSX Code] --> B[Babel Compilation]
B --> C[React.createElement]
C --> D[Virtual DOM Object]
D --> E[True DOM]
style A fill:#61dafb,color:#000
style C fill:#ff6b6b,color:#fff
(1) قاعدة العنصر الواحد
يجب أن تحتوي تعبيرات JSX على عنصر جذر. ولا يمكنها إرجاع عنصرين متجاورين.
// ❌ Error:No root element
return (
<h1>Title</h1>
<p>Paragraph</p>
)
// ✅ Correct:Use one <div> Package
return (
<div>
<h1>Title</h1>
<p>Paragraph</p>
</div>
)
// ✅ You can also use React Fragment(<></>),Does not incur additional DOM
return (
<>
<h1>Title</h1>
<p>Paragraph</p>
</>
)
(2) تضمين تعبيرات جافا سكريبت في JSX
استخدم الأقواس {} لتضمين أي تعبير JavaScript:
const name = 'Alice'
const age = 28
const colors = ['red', 'green', 'blue']
// Variable
<h1>Hello, {name}!</h1>
// Expression Evaluation
<p>Next year {age + 1} years old</p>
// Ternary Operator
<span>{age >= 18 ? 'Adulthood' : 'Minor'}</span>
// Function Call
<p>Today's Date:{new Date().toLocaleDateString()}</p>
// Array Length
<p>Total {colors.length} A Color</p>
(3) جدول مرجعي سريع: الاختلافات بين JSX و HTML
| ميزة | HTML | JSX |
|---|---|---|
| اسم الفئة | class="box" |
className="box" (كلمة "class" هي كلمة محجوزة في لغة جافا سكريبت) |
| سمة العلامة | for="input" |
htmlFor="input" (لأنها كلمة محجوزة في جافا سكريبت) |
| الأنماط المضمنة | style="color:red" |
style={{ color: 'red' }} (صيغة الكائن) |
| خاصية منطقية | disabled |
disabled={true} أو disabled |
| العلامات ذاتية الإغلاق | <br> <img> |
يجب إغلاقها: <br /> <img /> |
| ملاحظة | <!-- comment --> |
{/* comment */} |
| ربط الأحداث | onclick="handle()" |
onClick={handle} |
| اسم خاصية CSS | font-size (واصلة) |
fontSize (camelCase) |
▶ مثال: مقارنة بين JSX و HTML
// ============================================
// Example:The Same Card,HTML vs JSX Comparison of Writing Styles
// ============================================
// ---- HTML Writing Style ----
<div class="card" style="background-color: #f0f0f0; padding: 20px;">
<!-- TODO: replace with actual user avatar image -->
<img src="https://i.pravatar.cc/80" alt="Avatar" class="avatar">
<label for="name">Name:</label>
<input type="text" id="name" disabled>
<!-- This is a comment. -->
<button onclick="handleClick()">Click</button>
</div>
// ---- JSX Writing Style ----
<div className="card" style={{ backgroundColor: '#f0f0f0', padding: '20px' }}>
<!-- TODO: replace with actual user avatar image -->
<img src="https://i.pravatar.cc/80" alt="Avatar" className="avatar" />
<label htmlFor="name">Name:</label>
<input type="text" id="name" disabled={true} />
{/* This is a comment. */}
<button onClick={handleClick}>Click</button>
</div>
4. إنشاء مشروع React باستخدام Vite
(1) المتطلبات البيئية
| الأداة | متطلبات الإصدار | أمر الفحص | طريقة التثبيت |
|---|---|---|---|
| Node.js | ≥ 18.0 | node -v |
nodejs.org |
| npm | ≥ 9.0 | npm -v |
يتم تثبيته تلقائيًا مع Node.js |
| المحرر | أي | — | موصى به: VS Code |
(2) إنشاء مشروع وتشغيله
# 1. Create a Project(react-ts = React + TypeScript Template)
npm create vite@latest my-react-app -- --template react-ts
# 2. Go to the project directory
cd my-react-app
# 3. Install Dependencies
npm install
# 4. Start the development server
npm run dev
الناتج:
VITE v5.x ready in 320ms
➜ Local: http://localhost:5173/
➜ Network: http://192.168.1.100:5173/
افتح ملف http://localhost:5173/، وسترى صفحة الترحيب الافتراضية لـ Vite + React.
(3) هيكل دليل المشروع
my-react-app/
├── index.html # Entrance HTML Documents(Vite Parsing Entry Point)
├── package.json # Project Configuration and Dependencies
├── vite.config.ts # Vite Profile
├── tsconfig.json # TypeScript Layout
├── tsconfig.app.json # Applications TS Layout
├── tsconfig.node.json # Node.js Environment TS Layout
├── public/ # Static Resources(Will not be compiled)
│ └── vite.svg
└── src/ # Source Code Directory
├── main.tsx # App Entry Point(Render the root component)
├── App.tsx # Root Component
├── App.css # Root Component Styles
├── index.css # Global Styles
└── assets/ # Resource Files(will be compiled)
└── react.svg
| الملف | الغرض |
|---|---|
index.html |
نقطة دخول الصفحة؛ يبدأ Vite التحليل من هنا |
src/main.tsx إدخال JavaScript، عرض <App /> إلى #root |
|
src/App.tsx |
المكون الجذري؛ تبدأ جميع المكونات الأخرى من هنا |
vite.config.ts |
إعدادات Vite (الأسماء المستعارة، الخوادم الوكيلة، المكونات الإضافية، إلخ) |
▶ مثال: إنشاء أبسط مكون في React
// ============================================
// Example:from main.tsx The Complete Process for Navigating to the Page
// ============================================
// src/main.tsx —— App Entry Point
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.tsx'
import './index.css'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>
)
// src/App.tsx —— Root Component
function App() {
return (
<div>
<h1>Hello, React!</h1>
<p>This is my first one React Applications 🎉</p>
</div>
)
}
export default App
/* src/index.css —— Global Styles */
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 50px auto;
text-align: center;
}
5. React DevTools
تُعد React DevTools أداة أساسية لتصحيح أخطاء تطبيقات React، حيث تتيح لك عرض شجرة المكونات، وخصائص المكونات (props)، والحالة (state)، والأداء.
| طريقة التثبيت | الإجراءات |
|---|---|
| ملحق Chrome | ابحث عن "React Developer Tools" في متجر Chrome الإلكتروني |
| ملحقات فايرفوكس | ابحث عن «React Developer Tools» في ملحقات فايرفوكس |
| تطبيق مستقل | npx react-devtools |
▶ مثال: عرض مكون باستخدام DevTools
بعد التثبيت، افتح «أدوات المطور» (F12)، وسترى علامتي تبويب جديدتين: المكونات وأداة تحليل الأداء:
// in DevTools You can view these components in real time here Props and State
function App() {
const [count, setCount] = React.useState(0)
return (
<div>
<Header title="Counter" />
<Counter count={count} onIncrement={() => setCount(c => c + 1)} />
<Footer year={2026} />
</div>
)
}
// Components The panel will display:
// ├── App
// │ ├── Header (props: { title: "Counter" })
// │ ├── Counter (props: { count: 0, onIncrement: fn })
// │ └── Footer (props: { year: 2026 })
▶ المثال 4: الجمع بين العرض الشرطي في JSX والقوائم
function ProductCatalog({ products, isLoading, error }) {
if (isLoading) return <p style={{ textAlign: 'center', padding: 40 }}>Loading products...</p>
if (error) return <p style={{ color: '#ff4d4f', textAlign: 'center' }}>Error: {error}</p>
if (products.length === 0) return <p style={{ textAlign: 'center', color: '#999' }}>No products found</p>
return (
<div style={{ maxWidth: 600, margin: '0 auto' }}>
<h2>Product Catalog ({products.length})</h2>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(180px, 1fr))', gap: 16 }}>
{products.map(product => (
<div key={product.id} style={{ border: '1px solid #eee', borderRadius: 8, padding: 12 }}>
<h4 style={{ margin: '0 0 8px' }}>{product.name}</h4>
<p style={{ color: '#ff4d4f', fontWeight: 'bold', margin: '0 0 4px' }}>${product.price}</p>
{product.inStock ? (
<span style={{ color: '#52c41a', fontSize: 12 }}>In Stock</span>
) : (
<span style={{ color: '#999', fontSize: 12 }}>Out of Stock</span>
)}
</div>
))}
</div>
</div>
)
}
function CatalogPage() {
const sampleProducts = [
{ id: 1, name: 'Keyboard', price: 79, inStock: true },
{ id: 2, name: 'Mouse', price: 49, inStock: true },
{ id: 3, name: 'Monitor', price: 399, inStock: false },
]
return <ProductCatalog products={sampleProducts} isLoading={false} error={null} />
}
▶ المثال 5: شامل — تحليل ملف الدخول لمشروع React
// package.json Key Dependencies
// {
// "dependencies": { "react": "^18.3", "react-dom": "^18.3" },
// "devDependencies": { "vite": "^5.0", "@types/react": "^18.3", "@types/react-dom": "^18.3" }
// }
// src/main.jsx - App Entry Point
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
)
// src/App.jsx - Root Component
import { useState } from 'react'
function App() {
const [currentPage, setCurrentPage] = useState('home')
return (
<div style={{ fontFamily: 'sans-serif', maxWidth: 800, margin: '0 auto', padding: 20 }}>
<nav style={{ display: 'flex', gap: 16, marginBottom: 24, borderBottom: '2px solid #1890ff', paddingBottom: 12 }}>
{['home', 'about', 'contact'].map(page => (
<button key={page} onClick={() => setCurrentPage(page)}
style={{
padding: '8px 16px', border: 'none', borderRadius: 4, cursor: 'pointer',
background: currentPage === page ? '#1890ff' : '#f0f0f0',
color: currentPage === page ? 'white' : '#333',
}}>
{page.charAt(0).toUpperCase() + page.slice(1)}
</button>
))}
</nav>
<main>
{currentPage === 'home' && (
<div>
<h1>Welcome to React</h1>
<p>This is a minimal React app with Vite. Edit src/App.jsx and save to reload.</p>
<p>Current time: {new Date().toLocaleTimeString()}</p>
</div>
)}
{currentPage === 'about' && (
<div>
<h2>About</h2>
<p>Built with React 18 + Vite for fast development and HMR.</p>
</div>
)}
{currentPage === 'contact' && (
<div>
<h2>Contact</h2>
<p>Email us at hello@example.com</p>
</div>
)}
</main>
<footer style={{ marginTop: 40, paddingTop: 12, borderTop: '1px solid #eee', color: '#999', fontSize: 13 }}>
© 2026 React Tutorial. Built with Vite + React 18.
</footer>
</div>
)
}
export default App
❓ أسئلة شائعة
npm create vite@latest وnpx create-vite؟npm create vite@latest هي الصيغة الموصى بها لـ npm (تم تقديمها في الإصدار 7 وما بعده من npm)، والتي تبحث تلقائيًا عن أحدث حزمة create-vite وتقوم بتشغيلها. يمكن أيضًا استخدام npx create-vite. إذا كنت تستخدم pnpm أو yarn، فيمكنك استخدام pnpm create vite أو yarn create vite.class في JSX — ولماذا يتعين علينا استخدام className؟class هي كلمة رئيسية محجوزة في JavaScript. وبما أن JSX هي في الأساس لغة JavaScript، فلا يمكننا استخدام class. أثناء العرض، يقوم React تلقائيًا بتحويل className إلى سمة HTML class. وبالمثل، for → htmlFor.style في JSX أقواسًا معقوفة مزدوجة {{}}؟style={{ color: 'red' }} تعني: تمرير كائن JS { color: 'red' } كقيمة للسمة style..tsx على صيغة JSX (أي يمكنك كتابة علامات HTML بلغة TypeScript)، بينما لا يمكن لملفات .ts ذلك. يجب أن تحمل جميع الملفات التي تحتوي على مكونات React اللاحقة .tsx. أما الملفات التي تحتوي على منطق بحت (مثل الدوال المساعدة وتعريفات الأنواع) فيمكنها استخدام اللاحقة .ts.📖 ملخص
- استخدم
npm create vite@latest my-app -- --template react-tsلإعداد مشروع React + TypeScript بسرعة - JSX ليس لغة HTML، بل هو امتداد لبناء جملة JavaScript: استخدم
classNameبدلاً منclass، واستخدم{}لتضمين التعبيرات - يجب أن يحتوي كل تعبير JSX على عنصر جذر (يمكن أن يكون جزءًا
<></>) - يُعد Vite أسرع من CRA بأكثر من 10 أضعاف؛ ويستخدم هذا البرنامج التعليمي Vite طوال الوقت.
- React DevTools هي أداة أساسية لتصحيح الأخطاء تتيح لك عرض شجرة المكونات والحالة
📝 تمارين
- تمرين أساسي (مستوى الصعوبة ⭐): أنشئ مشروعًا جديدًا باستخدام React و TypeScript عبر Vite، وقم بتعديل
App.tsxلعرض اسمك وتقديمًا موجزًا عن نفسك. - تمرين (مستوى الصعوبة: ⭐⭐): أنشئ متغيرًا باسم
const isLoggedIn = trueفي مكون App، واستخدم العامل الثلاثي في JSX لعرض عبارة «مرحبًا بعودتك» أو «يرجى تسجيل الدخول». - التحقيق (مستوى الصعوبة: ⭐): افتح لوحة «المكونات» (Components) في React DevTools، واطلع على هيكل شجرة المكونات الخاص بالقالب الافتراضي لـ Vite، ثم التقط لقطة شاشة واحفظها.