رياكت واحدة من أشهر المكتبات اللي بتستخدمها الشركات والمطورين لبناء تطبيقات ويب سريعة وفعالة. بالكورس هذا رح نغطي كل المفاهيم الأساسية: من Virtual DOM وsetup البيئة، لحتى React Router وContext API وDeployment.
المواضيع اللي رح نمر فيها:
React مكتبة JavaScript بتساعدك تبني واجهات المستخدم بطريقة ذكية وسريعة. الطرق التقليدية بتخليك تعيد تحميل كل الصفحة عند أي تغيير، بس React بتشتغل بفكرة اسمها Virtual DOM.
شو هو الـ Virtual DOM؟ هو نسخة افتراضية خفيفة من الـ DOM الحقيقي، بتتم تخزينها بالميموري.
كيف بيشتغل:
هالعملية اسمها reconciliation، وهي اللي بتخلي React أسرع من الطرق التقليدية.
أول شيء تأكدوا من وجود Node.js:
node --version
npm --version
لإنشاء مشروع React، بنستخدم Vite:
npm create vite@latest react-app -- --template react-ts
cd react-app
npm install
npm run dev
اشترك في النشرة البريدية
دروس جديدة، مقالات، وأدوات مباشرة لبريدك.
افتحوا localhost:5173 وبتشوفوا الـ app شغالة.
| الملف/الفولدر | الوظيفة |
|---|---|
node_modules/ | الـ packages المنزّلة - لا تعدّلوها |
public/ | ملفات ثابتة مثل صور وأيقونات |
src/ | محل كتابة كل الكود |
package.json | الـ dependencies والـ scripts |
tsconfig.json | إعدادات TypeScript |
أهم الـ scripts:
npm run dev # تشغيل server للتطوير
npm run build # بناء الـ production build
npm run lint # فحص الكودReact كله عبارة عن components. كل صفحة وكل جزء من الـ UI هو component.
Component هي ببساطة function بترجع JSX:
function Todo() {
return (
<div>
<h2>Todo Title</h2>
<p>Todo Description</p>
</div>
);
}
export default Todo;JSX شبيهة بـ HTML بس فيها JavaScript extension - فيك تحط variables وexpressions جواتها:
function Todo() {
const age = 34;
return <p>Age: {age}</p>;
}قاعدة مهمة: كل component لازم يرجع element واحد. إذا بدك ترجع أكثر من element، لف إياهم بـ <div> أو باستخدام React Fragment:
// Fragment - ما بيضيف div إضافية بالـ DOM
function Todo() {
return (
<>
<h2>Title</h2>
<p>Description</p>
</>
);
}Props هي طريقة تمرير data من component أب لـ component ابن. هي arguments للـ function:
type TodoProps = {
title: string;
description: string;
};
function Todo({ title, description }: TodoProps) {
return (
<div>
<h3>{title}</h3>
<p>{description}</p>
</div>
);
}استخدام الـ component:
function App() {
return (
<>
<Todo title="Task One" description="Description one" />
<Todo title="Task Two" description="Description two" />
</>
);
}Props read-only - ما تعدّلوها من جوات الـ component.
في أكثر من طريقة للـ styling بالـ React:
// Inline style - لا يفضل إلا للحالات البسيطة
<div style={{ color: 'red' }}>text</div>
// CSS class - الطريقة المنصوحة
// NavBar.css
// .navlink { color: white; }
// NavBar.tsx
import './NavBar.css';
function NavBar() {
return <div className="navlink">text</div>;
}لاحظوا className مش class - هالكلمة محجوزة بالـ JavaScript.
State هي data بتتغير مع الوقت وبتؤثر على الـ UI. لإنشاء state نستخدم useState hook:
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
function increment() {
setCount(prev => prev + 1);
}
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Click me</button>
</div>
);
}useState بيرجع array من عنصرين:
count)setCount)مهم: استخدموا دايماً الـ callback form عند التحديث:
// الطريقة الصحيحة - دايماً up-to-date
setCount(prev => prev + 1);
// تجنبوا هاي الطريقة - ممكن تسبب bugs
setCount(count + 1);كل ما يتغير state، React بتعمل re-render للـ component تلقائياً.
Events بالـ React هي نفس browser events بالـ JavaScript:
function App() {
function handleClick() {
console.log('Clicked!');
}
return <button onClick={handleClick}>Click me</button>;
}لاستقبال معلومات عن الـ event:
function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
console.log('Value:', event.target.value);
console.log('Name:', event.target.name);
}
<input name="title" onChange={handleChange} />لعرض قائمة نستخدم map:
const todos = [
{ id: 1, title: 'Task 1', description: 'Desc 1' },
{ id: 2, title: 'Task 2', description: 'Desc 2' },
];
function TodoList() {
return (
<ul>
{todos.map(todo => (
<Todo key={todo.id} title={todo.title} description={todo.description} />
))}
</ul>
);
}الـ key مهم - بيساعد React تميّز كل element. استخدموا ID فريد دايماً، لا تستخدموا الـ index.
للتعامل مع forms، محتاجين نربط الـ input بـ state:
function TodoForm() {
const [todo, setTodo] = useState({ title: '', description: '' });
function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
setTodo(prev => ({
...prev,
[event.target.name]: event.target.value,
}));
}
function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault();
// معالجة الـ submit
console.log(todo);
}
return (
<form onSubmit={handleSubmit}>
<input
name="title"
placeholder="Title"
value={todo.title}
onChange={handleChange}
/>
<input
name="description"
placeholder="Description"
value={todo.description}
onChange={handleChange}
/>
<button type="submit">Add Todo</button>
</form>
);
}event.preventDefault() بيمنع الـ default behavior للـ form اللي هو refresh الـ page. الـ ...prev (spread operator) ضروري لحفظ القيم السابقة عند التحديث.
function TodoList() {
const [todos, setTodos] = useState<Todo[]>([]);
// باستخدام &&
return (
<div>
{todos.length === 0 && <p>No todos for today!</p>}
{todos.map(todo => <Todo key={todo.id} {...todo} />)}
</div>
);
}وباستخدام ternary operator:
{todos.length === 0
? <p>No todos for today!</p>
: <p>You have {todos.length} todos</p>
}useEffect بتستخدم لمزامنة الـ component مع شيء خارجي - مثل جلب data من server أو local storage.
import { useEffect, useState } from 'react';
function TodoList() {
const [todos, setTodos] = useState<Todo[]>([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/todos')
.then(res => res.json())
.then(data => setTodos(data));
}, []); // الـ empty array بتخلي الـ effect يشتغل مرة واحدة
return (/* ... */);
}الـ dependency array:
| الـ dependency array | متى يشتغل الـ effect |
|---|---|
| بدون array | كل re-render |
[] array فاضي | مرة واحدة عند mount الـ component |
[variable] | عند mount وكل ما يتغير الـ variable |
نصيحة: استخدموا useEffect بأقل ما يمكن. بشكل عام، الاستخدام المناسب الوحيد هو جلب data من مصدر خارجي.
تجنبوا الـ infinite loop:
// هالكود بيسبب infinite loop!
useEffect(() => {
fetchData().then(data => setTodos(data));
}, [todos]); // todos بتتغير بعد كل fetch، بيسبب loop لانهائي
// الصح - array فاضي لجلب data مرة واحدة
useEffect(() => {
fetchData().then(data => setTodos(data));
}, []);لإضافة أكثر من صفحة، نستخدم React Router:
npm install react-router-domبالـ main.tsx:
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import HomePage from './pages/HomePage';
import AboutPage from './pages/AboutPage';
const router = createBrowserRouter([
{ path: '/', element: <HomePage /> },
{ path: '/about', element: <AboutPage /> },
]);
ReactDOM.createRoot(document.getElementById('root')!).render(
<RouterProvider router={router} />
);للتنقل بين الصفحات بدون refresh، استخدموا Link مش a tag:
import { Link } from 'react-router-dom';
function NavBar() {
return (
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
);
}Context API بتحل مشكلة Prop Drilling - وهي لما بتحتاج تمرر data من component أعلى لـ component أسفل بكثير مستويات.
أول شيء، ننشئ الـ context:
import { createContext } from 'react';
export const ThemeContext = createContext<string | null>(null);بعدين نلف الـ app أو جزء منها بالـ Provider:
function App() {
return (
<ThemeContext.Provider value="dark">
<RouterProvider router={router} />
</ThemeContext.Provider>
);
}وبأي component بنحتاج فيه الـ data:
import { useContext } from 'react';
import { ThemeContext } from './ThemeContext';
function TodoItem() {
const theme = useContext(ThemeContext);
console.log(theme); // 'dark'
return <div className={theme}>...</div>;
}هيكي فينا نوصل الـ data مباشرةً لأي component بدون ما نعمل prop drilling عبر كل المستويات.
فيكن تحطوا أي نوع بيانات بالـ context - objects وarrays وfunctions كلها تشتغل.
بعد ما تكمل الـ app، نبنيها ونعمل deploy:
npm run buildهيك بينشئ folder اسمه dist فيه كل الملفات المبنية.
روحوا على netlify.com وعملوا sign up، بعدين:
dist folder وحطوه على الـ drop zoneبعد ثواني رح يطلع عندكم URL تقدروا تشاركوه مع أي شخص.
React كبير الموضوع وهذا بس البداية. في hooks كثير ثانية مثل useRef وuseMemo وبناء custom hooks، وموضوع server components بالـ React 19، وكلهم رح يكون فيهم مواد مخصصة قريباً.