لماذا React هي المكتبة الأكثر طلباً في سوق العمل؟
React.js هي مكتبة JavaScript لبناء واجهات المستخدم، طورتها Facebook (Meta). تستخدمها شركات مثل Netflix، Instagram، Airbnb، و WhatsApp Web. إذا أردت العمل كمطور واجهات أمامية، فإتقان React هو أهم مهارة يمكنك تعلمها.
ما يميز React:
- المكونات (Components): تقسم الواجهة لقطع صغيرة قابلة لإعادة الاستخدام
- Virtual DOM: تحديث فقط الأجزاء المتغيرة بدل إعادة رسم كل الصفحة
- JSX: كتابة HTML داخل JavaScript بطريقة سهلة
- Hooks: إدارة الحالة والتأثيرات الجانبية بأسلوب بسيط
إعداد بيئة العمل
# إنشاء مشروع React جديد باستخدام Vite (أسرع من CRA)
npm create vite@latest my-app -- --template react
# الدخول للمجلد وتثبيت المكتبات
cd my-app
npm install
# تشغيل خادم التطوير
npm run dev
# التطبيق يعمل على http://localhost:5173
هيكل المشروع
my-app/
├── public/
├── src/
│ ├── App.jsx # المكون الرئيسي
│ ├── main.jsx # نقطة البداية
│ ├── App.css
│ ├── components/ # المكونات
│ │ ├── Header.jsx
│ │ ├── ProductCard.jsx
│ │ └── Footer.jsx
│ └── hooks/ # Hooks مخصصة
│ └── useFetch.js
├── package.json
└── vite.config.js
المكونات: أساس React
كل شيء في React هو مكون (Component) — وظيفة JavaScript تُرجع JSX:
أول مكون لك
// components/Welcome.jsx
function Welcome() {
return (
<div className="welcome">
<h1>مرحباً بك في React! 🚀</h1>
<p>هذا أول مكون لك</p>
</div>
);
}
export default Welcome;
المكونات مع Props (الخصائص)
// components/ProductCard.jsx
function ProductCard({ name, price, image, onAddToCart }) {
return (
<div className="product-card">
<img src={image} alt={name} />
<h3>{name}</h3>
<p className="price">{price} د.م</p>
<button onClick={() => onAddToCart(name)}>
أضف للسلة 🛒
</button>
</div>
);
}
// الاستخدام
<ProductCard
name="هاتف ذكي"
price={2500}
image="/phone.jpg"
onAddToCart={(name) => alert(`تمت إضافة ${name}`)}
/>
إدارة الحالة مع useState
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<h2>العداد: {count}</h2>
<button onClick={() => setCount(count + 1)}>+1</button>
<button onClick={() => setCount(count - 1)}>-1</button>
<button onClick={() => setCount(0)}>إعادة تعيين</button>
</div>
);
}
// مثال أكثر تعقيداً: نموذج تسجيل
function SignupForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
password: ''
});
const [errors, setErrors] = useState({});
const handleChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({ ...prev, [name]: value }));
};
const handleSubmit = (e) => {
e.preventDefault();
// التحقق
const newErrors = {};
if (!formData.name) newErrors.name = 'الاسم مطلوب';
if (!formData.email.includes('@')) newErrors.email = 'بريد غير صحيح';
if (formData.password.length < 6) newErrors.password = 'كلمة المرور قصيرة';
if (Object.keys(newErrors).length > 0) {
setErrors(newErrors);
return;
}
console.log('بيانات التسجيل:', formData);
};
return (
<form onSubmit={handleSubmit}>
<input name="name" placeholder="الاسم" value={formData.name} onChange={handleChange} />
{errors.name && <span className="error">{errors.name}</span>}
<input name="email" placeholder="البريد الإلكتروني" value={formData.email} onChange={handleChange} />
{errors.email && <span className="error">{errors.email}</span>}
<input name="password" type="password" placeholder="كلمة المرور" value={formData.password} onChange={handleChange} />
{errors.password && <span className="error">{errors.password}</span>}
<button type="submit">تسجيل</button>
</form>
);
}
جلب البيانات مع useEffect
import { useState, useEffect } from 'react';
function ProductList() {
const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchProducts() {
try {
const response = await fetch('https://fakestoreapi.com/products');
const data = await response.json();
setProducts(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}
fetchProducts();
}, []); // [] = يعمل مرة واحدة عند تحميل المكون
if (loading) return <div>جاري التحميل...</div>;
if (error) return <div>خطأ: {error}</div>;
return (
<div className="products-grid">
{products.map(product => (
<ProductCard
key={product.id}
name={product.title}
price={product.price}
image={product.image}
/>
))}
</div>
);
}
إنشاء Hook مخصص
// hooks/useFetch.js - Hook قابل لإعادة الاستخدام
import { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const controller = new AbortController();
async function fetchData() {
try {
const response = await fetch(url, { signal: controller.signal });
const result = await response.json();
setData(result);
} catch (err) {
if (err.name !== 'AbortError') setError(err.message);
} finally {
setLoading(false);
}
}
fetchData();
return () => controller.abort(); // تنظيف عند إلغاء المكون
}, [url]);
return { data, loading, error };
}
// الاستخدام - أبسط بكثير!
function ProductList() {
const { data: products, loading, error } = useFetch('https://fakestoreapi.com/products');
if (loading) return <div>جاري التحميل...</div>;
if (error) return <div>خطأ: {error}</div>;
return products.map(p => <ProductCard key={p.id} {...p} />);
}
عرض القوائم والتصفية
function FilterableProductList() {
const [search, setSearch] = useState('');
const [category, setCategory] = useState('all');
const { data: products } = useFetch('https://fakestoreapi.com/products');
const filtered = products?.filter(p => {
const matchesSearch = p.title.toLowerCase().includes(search.toLowerCase());
const matchesCategory = category === 'all' || p.category === category;
return matchesSearch && matchesCategory;
});
return (
<div>
<input placeholder="ابحث عن منتج..." value={search} onChange={e => setSearch(e.target.value)} />
<select value={category} onChange={e => setCategory(e.target.value)}>
<option value="all">كل الأقسام</option>
<option value="electronics">إلكترونيات</option>
<option value="jewelery">مجوهرات</option>
<option value="men's clothing">ملابس رجالية</option>
</select>
<div className="grid">
{filtered?.map(p => <ProductCard key={p.id} {...p} />)}
</div>
</div>
);
}
ملخص المهارات المكتسبة
- إنشاء مشروع React باستخدام Vite
- بناء مكونات قابلة لإعادة الاستخدام مع Props
- إدارة الحالة باستخدام useState
- جلب البيانات من API باستخدام useEffect
- إنشاء Hooks مخصصة لإعادة استخدام المنطق
- بناء نماذج مع التحقق من البيانات
- فلترة وعرض القوائم ديناميكياً
الخطوة التالية: أضف React Router للتنقل بين الصفحات، واستخدم Context API أو Redux لإدارة الحالة العامة، ثم ابنِ مشروعاً كاملاً مثل متجر إلكتروني أو تطبيق مهام.