تطوير تطبيقات حديثة باستخدام React
دليل شامل لإنشاء تطبيقات ويب عالية الأداء وسهلة الصيانة باستخدام React.
InSkillCoach
تطوير تطبيقات حديثة باستخدام React
تُعدّ React واحدة من أشهر مكتبات JavaScript لبناء واجهات المستخدم. طوّرتها شركة Facebook (Meta) وتتولى صيانتها، وهي تتيح بناء تطبيقات ويب معقدة باستخدام مكوّنات قابلة لإعادة الاستخدام وإدارة فعّالة للحالة.
لماذا نختار React؟
- النهج التصريحي: تصف الشكل الذي ينبغي أن تظهر به واجهتك، وتتولى React تحديثها
- قائمة على المكوّنات: أنشئ عناصر واجهة مغلّفة وقابلة لإعادة الاستخدام
- منظومة غنية: مجموعة واسعة من المكتبات والأدوات المكمّلة
- مجتمع كبير: دعم وموارد وتحديثات منتظمة
- أداء محسّن: Virtual DOM وعملية المطابقة (reconciliation) لتحديثات فعّالة
- معتمدة لدى كبريات الشركات: Facebook وInstagram وNetflix وAirbnb وغيرها
إعداد مشروع React
الإنشاء باستخدام Create React App
Create React App أداة رسمية تتيح بدء مشروع React بسرعة:
# Installation
npx create-react-app mon-application
# Démarrage
cd mon-application
npm start
استخدام Vite (بديل حديث)
يوفّر Vite أوقات بناء أسرع وتجربة تطوير أفضل:
# Installation
npm create vite@latest mon-application -- --template react
# Démarrage
cd mon-application
npm install
npm run dev
أساسيات React
المكوّنات
المكوّنات هي اللبنات الأساسية لأي تطبيق React:
// Composant fonctionnel
function Salutation(props) {
return <h1>Bonjour, {props.nom} !</h1>;
}
// Utilisation
<Salutation nom="Alice" />
JSX
JSX امتداد لصيغة اللغة يتيح كتابة HTML داخل JavaScript:
const element = <h1>Bonjour, monde !</h1>;
// Avec expressions JavaScript
const nom = "Alice";
const element = <h1>Bonjour, {nom} !</h1>;
// Avec attributs
const element = <img src={user.avatarUrl} alt="Avatar" />;
// Éléments imbriqués
const element = (
<div>
<h1>Titre</h1>
<p>Paragraphe</p>
</div>
);
الخصائص (Props)
تتيح الخصائص (props) تمرير البيانات من مكوّن أب إلى مكوّن ابن:
// Définition du composant
function Carte(props) {
return (
<div className="carte">
<h2>{props.titre}</h2>
<p>{props.description}</p>
{props.children}
</div>
);
}
// Utilisation
<Carte
titre="Mon titre"
description="Ma description"
>
<button>En savoir plus</button>
</Carte>
الحالة (State)
تتيح الحالة تخزين بيانات يمكن أن تتغير بمرور الوقت:
import { useState } from 'react';
function Compteur() {
// Déclaration d'un état
const [compteur, setCompteur] = useState(0);
return (
<div>
<p>Vous avez cliqué {compteur} fois</p>
<button onClick={() => setCompteur(compteur + 1)}>
Cliquez ici
</button>
</div>
);
}
دورة الحياة مع الـ Hooks
تتيح الـ Hooks استخدام الحالة وميزات React الأخرى داخل المكوّنات الوظيفية:
import { useState, useEffect } from 'react';
function ExempleEffet() {
const [compteur, setCompteur] = useState(0);
// Similaire à componentDidMount et componentDidUpdate
useEffect(() => {
// Met à jour le titre du document
document.title = `Vous avez cliqué ${compteur} fois`;
// Fonction de nettoyage (similaire à componentWillUnmount)
return () => {
document.title = 'React App';
};
}, [compteur]); // S'exécute uniquement si compteur change
return (
<div>
<p>Vous avez cliqué {compteur} fois</p>
<button onClick={() => setCompteur(compteur + 1)}>
Cliquez ici
</button>
</div>
);
}
إدارة الأحداث
تستخدم React صيغة مشابهة لـ HTML لإدارة الأحداث:
function Bouton() {
function handleClick(e) {
e.preventDefault();
console.log('Le bouton a été cliqué');
}
return (
<button onClick={handleClick}>
Cliquez ici
</button>
);
}
العرض الشرطي
يمكنك عرض عناصر مختلفة بحسب شروط معينة:
function Connexion(props) {
const estConnecte = props.estConnecte;
return (
<div>
{estConnecte ? (
<BoutonDeconnexion />
) : (
<BoutonConnexion />
)}
</div>
);
}
// Autre approche
function Message(props) {
const nonLu = props.messagesNonLus.length;
return (
<div>
<h1>Bonjour !</h1>
{nonLu > 0 && (
<p>Vous avez {nonLu} message(s) non lu(s).</p>
)}
</div>
);
}
القوائم والمفاتيح
لعرض قوائم من العناصر، استخدم map() ومفاتيح فريدة:
function ListeArticles(props) {
const articles = props.articles;
return (
<ul>
{articles.map((article) => (
<li key={article.id}>
{article.titre}
</li>
))}
</ul>
);
}
الإدارة المتقدمة للحالة
Context API
تتيح Context API مشاركة البيانات بين المكوّنات دون المرور عبر الـ props:
// Création du contexte
const ThemeContext = React.createContext('light');
// Fournisseur de contexte
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
// Consommation du contexte avec useContext
function Bouton() {
const theme = useContext(ThemeContext);
return (
<button className={theme}>
Je suis stylisé selon le thème {theme}
</button>
);
}
useReducer لإدارة الحالة المعقدة
يُفضَّل استخدام useReducer على useState عندما تكون الحالات معقدة:
import { useReducer } from 'react';
// Définition du reducer
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { compteur: state.compteur + 1 };
case 'decrement':
return { compteur: state.compteur - 1 };
default:
throw new Error();
}
}
function Compteur() {
// Utilisation du reducer
const [state, dispatch] = useReducer(reducer, { compteur: 0 });
return (
<div>
Compteur: {state.compteur}
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</div>
);
}
مكتبات إدارة الحالة
بالنسبة إلى التطبيقات الأكثر تعقيدًا، يمكنك استخدام مكتبات متخصصة:
Redux
// Actions
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';
// Action creators
function increment() {
return { type: INCREMENT };
}
// Reducer
function compteurReducer(state = { valeur: 0 }, action) {
switch (action.type) {
case INCREMENT:
return { valeur: state.valeur + 1 };
case DECREMENT:
return { valeur: state.valeur - 1 };
default:
return state;
}
}
// Store
const store = createStore(compteurReducer);
// Composant connecté
function Compteur({ valeur, increment, decrement }) {
return (
<div>
<span>{valeur}</span>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
);
}
const mapStateToProps = state => ({
valeur: state.valeur
});
const mapDispatchToProps = {
increment,
decrement
};
export default connect(mapStateToProps, mapDispatchToProps)(Compteur);
Zustand (بديل حديث)
import create from 'zustand';
// Création du store
const useStore = create(set => ({
compteur: 0,
increment: () => set(state => ({ compteur: state.compteur + 1 })),
decrement: () => set(state => ({ compteur: state.compteur - 1 })),
}));
// Utilisation dans un composant
function Compteur() {
const { compteur, increment, decrement } = useStore();
return (
<div>
<span>{compteur}</span>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
);
}
التوجيه باستخدام React Router
تتيح React Router إدارة التنقل داخل تطبيق React:
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">Accueil</Link>
<Link to="/a-propos">À propos</Link>
<Link to="/contact">Contact</Link>
</nav>
<Routes>
<Route path="/" element={<Accueil />} />
<Route path="/a-propos" element={<APropos />} />
<Route path="/contact" element={<Contact />} />
<Route path="/produits/:id" element={<DetailProduit />} />
<Route path="*" element={<PageNonTrouvee />} />
</Routes>
</BrowserRouter>
);
}
// Accès aux paramètres d'URL
import { useParams } from 'react-router-dom';
function DetailProduit() {
const { id } = useParams();
return <h1>Détail du produit {id}</h1>;
}
النماذج في React
النماذج المتحكَّم بها
في النموذج المتحكَّم به، تتولى React إدارة حالة النموذج:
import { useState } from 'react';
function FormulaireConnexion() {
const [email, setEmail] = useState('');
const [motDePasse, setMotDePasse] = useState('');
function handleSubmit(e) {
e.preventDefault();
console.log('Email:', email);
console.log('Mot de passe:', motDePasse);
}
return (
<form onSubmit={handleSubmit}>
<div>
<label>
Email:
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</label>
</div>
<div>
<label>
Mot de passe:
<input
type="password"
value={motDePasse}
onChange={(e) => setMotDePasse(e.target.value)}
required
/>
</label>
</div>
<button type="submit">Se connecter</button>
</form>
);
}
مكتبات النماذج
بالنسبة إلى النماذج المعقدة، استخدم مكتبات مثل Formik أو React Hook Form:
// Avec React Hook Form
import { useForm } from 'react-hook-form';
function FormulaireInscription() {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = data => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>Nom</label>
<input {...register('nom', { required: 'Le nom est requis' })} />
{errors.nom && <p>{errors.nom.message}</p>}
</div>
<div>
<label>Email</label>
<input
{...register('email', {
required: 'L\'email est requis',
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: 'Adresse email invalide'
}
})}
/>
{errors.email && <p>{errors.email.message}</p>}
</div>
<button type="submit">S'inscrire</button>
</form>
);
}
تحسين الأداء
React.memo
تتيح React.memo تفادي عمليات إعادة العرض غير الضرورية للمكوّنات الوظيفية:
const MonComposant = React.memo(function MonComposant(props) {
// Votre composant
});
useMemo وuseCallback
تتيح هاتان الدالتان (hooks) حفظ القيم والدوال في الذاكرة:
import { useMemo, useCallback } from 'react';
function ExempleOptimisation({ a, b }) {
// Mémorise le résultat du calcul
const resultat = useMemo(() => {
console.log('Calcul coûteux...');
return a * b;
}, [a, b]); // Recalcule uniquement si a ou b change
// Mémorise la fonction
const handleClick = useCallback(() => {
console.log('Bouton cliqué avec résultat:', resultat);
}, [resultat]); // Recrée uniquement si resultat change
return (
<div>
<p>Résultat: {resultat}</p>
<button onClick={handleClick}>Cliquer</button>
</div>
);
}
التحميل الكسول (Lazy Loading)
يتيح التحميل الكسول تقسيم تطبيقك إلى أجزاء أصغر:
import { lazy, Suspense } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
// Chargement paresseux des composants
const Accueil = lazy(() => import('./pages/Accueil'));
const APropos = lazy(() => import('./pages/APropos'));
const Contact = lazy(() => import('./pages/Contact'));
function App() {
return (
<BrowserRouter>
<Suspense fallback={<div>Chargement...</div>}>
<Routes>
<Route path="/" element={<Accueil />} />
<Route path="/a-propos" element={<APropos />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</Suspense>
</BrowserRouter>
);
}
الاختبارات في React
اختبارات الوحدة باستخدام Jest وReact Testing Library
// Composant à tester
function Salutation({ nom }) {
return <h1>Bonjour, {nom} !</h1>;
}
// Test
import { render, screen } from '@testing-library/react';
import Salutation from './Salutation';
test('affiche le message de salutation', () => {
render(<Salutation nom="Alice" />);
const element = screen.getByText(/bonjour, alice !/i);
expect(element).toBeInTheDocument();
});
اختبارات التفاعل
import { render, screen, fireEvent } from '@testing-library/react';
import Compteur from './Compteur';
test('incrémente le compteur lorsque le bouton est cliqué', () => {
render(<Compteur />);
// Vérifier la valeur initiale
expect(screen.getByText(/compteur: 0/i)).toBeInTheDocument();
// Cliquer sur le bouton
fireEvent.click(screen.getByText('+'));
// Vérifier la nouvelle valeur
expect(screen.getByText(/compteur: 1/i)).toBeInTheDocument();
});
نشر تطبيق React
البناء للإنتاج (Build)
# Avec Create React App
npm run build
# Avec Vite
npm run build
الاستضافة الثابتة
يمكنك نشر تطبيقك على منصات مثل:
- Netlify: اسحب مجلد
buildوأفلته، أو اضبط نشرًا مستمرًا - Vercel: محسّنة لتطبيقات React، مع نشر تلقائي انطلاقًا من GitHub
- GitHub Pages: مثالية للمشاريع الشخصية أو مفتوحة المصدر
- Firebase Hosting: حل متكامل يشمل المصادقة وقاعدة البيانات
أفضل الممارسات
- نظّم مشروعك: رتّب ملفاتك بحسب الميزة أو النوع
- استخدم المكوّنات الوظيفية: فهي أبسط وأكثر كفاءة مع الـ Hooks
- تجنّب تمرير الـ props عبر مستويات عديدة (props drilling): استخدم Context أو مكتبة لإدارة الحالة
- اكتب الاختبارات: تأكد من أن تطبيقك يعمل كما هو متوقع
- حسّن الأداء: استخدم React.memo وuseMemo وuseCallback بحكمة
- اتبع مبادئ SOLID: أنشئ مكوّنات ذات مسؤولية واحدة
- استخدم TypeScript: أضف الكتابة الساكنة لتفادي الأخطاء
- وثّق مكوّناتك: استخدم أدوات مثل Storybook
الخلاصة
تُعدّ React مكتبة قوية تتيح إنشاء واجهات مستخدم حديثة وعالية الأداء. وبفضل مرونتها ونظامها البيئي الغني، تُعتبر خيارًا ممتازًا لتطوير تطبيقات الويب بمختلف أحجامها.
وبإتقان المفاهيم الأساسية وأفضل الممارسات المعروضة في هذه المقالة، ستتمكن من إنشاء تطبيقات React متينة وسهلة الصيانة وقابلة للتطوير.
نبذة عن InSkillCoach
خبير في التدريب والتقنيات
مدرّب متخصص في التقنيات المتقدمة والذكاء الاصطناعي، تدعمه شركة GNeurone Inc.
الشهادات:
- AWS Certified Solutions Architect – Professional
- شهادات Google Cloud
- Microsoft Certified: DevOps Engineer Expert
- Certified Kubernetes Administrator (CKA)
- CompTIA Security+
التعليقات
التعليقات مدعومة عبر GitHub Discussions
سجّل الدخول باستخدام GitHub للمشاركة في النقاش