🎯 ما هي Context API ؟
Context API هي طريقة في React لتمرير البيانات بين المكونات بدون الحاجة لتمرير props يدويًا عبر كل المستويات.
يعني بدل ما تعمل:
<App>
<Parent>
<Child>
<GrandChild name="Ahmad" /> {/* تمرير عبر عدة طبقات */}
</Child>
</Parent>
</App>JSXتقدر تستخدم context وتخلي كل المكونات تشوف نفس القيمة مباشرة، بدون تمرير props يدويًا.
🧠 فكر فيها مثل مخزن صغير داخل التطبيق يمكن لأي مكون الوصول إليه.
🧩 متى نحتاجها؟
- لما عندك بيانات أو حالة يحتاجها أكثر من مكون في أماكن بعيدة عن بعضها.
- أمثلة شائعة:
- لغة الموقع (عربي/إنجليزي)
- وضع الإضاءة (فاتح/داكن)
- المستخدم المسجّل حاليًا
- سلة التسوق
- إعدادات عامة للتطبيق
⚙️ طريقة الاستخدام
- إنشاء الـ Context
- تغليف المكونات بـ Provider
- استهلاك البيانات بـ useContext
مثال عملي بسيط 👇
🔹 1. إنشاء Context
import { createContext, useState } from "react";
export const ThemeContext = createContext(); // الخطوة الأولى
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState("light");
const toggleTheme = () =>
setTheme((prev) => (prev === "light" ? "dark" : "light"));
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}JSX🔹 2. تغليف التطبيق بـ Provider (عادة في main.jsx أو App.jsx)
import ReactDOM from "react-dom/client";
import App from "./App";
import { ThemeProvider } from "./ThemeContext";
ReactDOM.createRoot(document.getElementById("root")).render(
<ThemeProvider>
<App />
</ThemeProvider>
);JSX🔹 3. استهلاك القيم داخل مكون (باستخدام useContext)
import { useContext } from "react";
import { ThemeContext } from "./ThemeContext";
export default function Child() {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<div
style={{
background: theme === "light" ? "#fff" : "#333",
color: theme === "light" ? "#000" : "#fff",
padding: 20,
textAlign: "center",
}}
>
<p>الوضع الحالي: {theme}</p>
<button onClick={toggleTheme}>تبديل الوضع</button>
</div>
);
}JSX💡 النتيجة:
كل مكون داخل <ThemeProvider> يقدر يقرأ أو يغيّر theme بدون تمريرها كـ prop.
حتى لو كان مكون “حفيد” بعيد جدًا!
🔥 ملاحظات مهمة:
- القيم اللي داخل الـ context تُخزَّن في الذاكرة (state).
- كل مرة تتغيّر فيها القيمة داخل الـ
Provider→ يُعاد رندر كل المكونات اللي تستخدمها. - استخدمها للقيم العامة فقط، مو لكل شيء! (لا تكثرها بدون داعٍ).
- أحيانًا يُفضل مكتبات إدارة الحالة (مثل Redux أو Zustand) لو التطبيق كبير جدًا.
📦 مثال كامل صغير:
// ThemeContext.js
import { createContext, useState } from "react";
export const ThemeContext = createContext();
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState("light");
const toggle = () => setTheme(t => (t === "light" ? "dark" : "light"));
return (
<ThemeContext.Provider value={{ theme, toggle }}>
{children}
</ThemeContext.Provider>
);
};JSX// App.jsx
import { useContext } from "react";
import { ThemeContext } from "./ThemeContext";
export default function App() {
const { theme, toggle } = useContext(ThemeContext);
return (
<div style={{
background: theme === "light" ? "#fff" : "#222",
color: theme === "light" ? "#000" : "#fff",
height: "100vh",
textAlign: "center",
paddingTop: 50
}}>
<h1>الوضع الحالي: {theme}</h1>
<button onClick={toggle}>بدّل الوضع</button>
</div>
);
}JSX// main.jsx
import { createRoot } from "react-dom/client";
import { ThemeProvider } from "./ThemeContext";
import App from "./App";
createRoot(document.getElementById("root")).render(
<ThemeProvider>
<App />
</ThemeProvider>
);JSX🧠 ملخّص سريع:
| الخطوة | الوظيفة |
|---|---|
createContext() | إنشاء السياق |
<Context.Provider> | تمرير القيم إلى الشجرة |
useContext(Context) | قراءة القيم داخل أي مكون |
Provider | يغلّف المكونات التي تحتاج الوصول للسياق |
🍉 أولًا: ليش ممكن تحتاج أكثر من Context؟
أحيانًا التطبيق فيه أكثر من نوع بيانات عام لازم يتشارك بين المكونات:
مثلاً:
ThemeContext→ لإدارة الوضع الليلي والفاتحAuthContext→ لتخزين المستخدم المسجّلLanguageContext→ للغة الموقعCartContext→ لسلة التسوّق
لو جمعت كل هالبيانات في Context واحد، بصير ضخم ومعقّد.
فالأفضل تفصلهم كل واحد في ملفه.
🍉🍈 مثال عملي: Theme + Auth Context
1️⃣ إنشاء ThemeContext
// ThemeContext.js
import { createContext, useState } from "react";
export const ThemeContext = createContext();
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState("light");
const toggleTheme = () =>
setTheme((prev) => (prev === "light" ? "dark" : "light"));
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};JSX2️⃣ إنشاء AuthContext
// AuthContext.js
import { createContext, useState } from "react";
export const AuthContext = createContext();
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
const login = (name) => setUser({ name });
const logout = () => setUser(null);
return (
<AuthContext.Provider value={{ user, login, logout }}>
{children}
</AuthContext.Provider>
);
};JSX3️⃣ تغليفهم معًا
في main.jsx أو ملف مركزي خاص بـ “اللفّاف” (Wrapper):
import ReactDOM from "react-dom/client";
import App from "./App";
import { ThemeProvider } from "./ThemeContext";
import { AuthProvider } from "./AuthContext";
ReactDOM.createRoot(document.getElementById("root")).render(
<ThemeProvider>
<AuthProvider>
<App />
</AuthProvider>
</ThemeProvider>
);JSX💡 الترتيب مهم فقط لو أحد الـ Contexts يعتمد على الآخر.
(مثلاً لوAuthContextيعتمد على theme، لازم يجي داخله.)
4️⃣ استخدام أكثر من Context داخل نفس المكون
import { useContext } from "react";
import { ThemeContext } from "./ThemeContext";
import { AuthContext } from "./AuthContext";
export default function Profile() {
const { theme, toggleTheme } = useContext(ThemeContext);
const { user, login, logout } = useContext(AuthContext);
return (
<div
style={{
background: theme === "light" ? "#fff" : "#333",
color: theme === "light" ? "#000" : "#fff",
padding: 20,
textAlign: "center",
}}
>
<h2>الوضع الحالي: {theme}</h2>
<button onClick={toggleTheme}>بدّل اللون</button>
<hr />
{user ? (
<>
<p>مرحباً يا {user.name} 👋</p>
<button onClick={logout}>تسجيل الخروج</button>
</>
) : (
<button onClick={() => login("أحمد")}>تسجيل الدخول</button>
)}
</div>
);
}JSX🧠 نصيحة احترافية:
لو زادت كثير وصار عندك أكثر من 3–4 Contexts،
اعمل ملف اسمه مثلاً AppProviders.jsx لتجمعهم بسهولة:
// AppProviders.jsx
import { ThemeProvider } from "./ThemeContext";
import { AuthProvider } from "./AuthContext";
export const AppProviders = ({ children }) => (
<ThemeProvider>
<AuthProvider>{children}</AuthProvider>
</ThemeProvider>
);JSXثم في main.jsx:
import { AppProviders } from "./AppProviders";
createRoot(document.getElementById("root")).render(
<AppProviders>
<App />
</AppProviders>
);JSX🧩 ملخّص سريع:
| الحالة | الحل |
|---|---|
| عندك بيانات عامة كثيرة | افصلها في أكثر من Context |
| تحتاج الوصول لأكثر من واحدة | استخدم useContext لكل واحدة |
| عندك Contexts كثيرة | لفها بـ AppProviders لتبسيط الكود |