useContext چیه و چرا مفیده؟
در React وقتی دادهای مثل نام کاربر، تم سایت یا زبان نیاز داره بین چندین کامپوننت استفاده بشه،
معمولاً باید اون رو از والد به فرزند از طریق props ارسال کنیم.
این کار اگه ساختار کامپوننتها زیاد باشه، به اصطلاح باعث Prop Drilling میشه (یعنی ارسال بیمورد داده در چند سطح).
useContext این مشکل رو حل میکنه.
باهاش میتونی یه context بسازی که داده رو در اختیار همهی کامپوننتهای زیرمجموعه قرار بده،
بدون اینکه نیازی به ارسال دستی props باشه.
روش استفاده از useContext
برای استفاده از useContext سه مرحله ساده داری:
const ThemeContext = createContext();
<ThemeContext.Provider value={value}> ... </ThemeContext.Provider>
const theme = useContext(ThemeContext);
به همین سادگی، هر کامپوننت داخل Provider به دادهی context دسترسی داره.
مثال ساده از useContext
بیایید یه مثال عملی ببینیم:
فرض کن میخوای تم (روشن یا تاریک) رو بین چند کامپوننت به اشتراک بذاری:
import { createContext, useContext, useState } from "react";
const ThemeContext = createContext();
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>
);
}
function Toolbar() {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<div style={{ background: theme === "dark" ? "#0f172a" : "#f9fafb", padding: "10px" }}>
<p>تم فعلی: {theme}</p>
<button onClick={toggleTheme}>تغییر تم</button>
</div>
);
}
export default function App() {
return (
<ThemeProvider>
<Toolbar />
</ThemeProvider>
);
}
حالا هر کامپوننتی که داخل ThemeProvider قرار داره،
میتونه از useContext(ThemeContext) برای دسترسی یا تغییر تم استفاده کنه.
ترکیب useContext با useReducer
ترکیب useContext با
useReducer
یکی از محبوبترین الگوهای React برای مدیریت state سراسریه.
این ترکیب مثل Redux عمل میکنه اما سبکتر و بدون وابستگی به کتابخانهی خارجی.
const AppContext = createContext();
function reducer(state, action) {
switch (action.type) {
case "increment":
return { count: state.count + 1 };
default:
return state;
}
}
function AppProvider({ children }) {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<AppContext.Provider value={{ state, dispatch }}>
{children}
</AppContext.Provider>
);
}
function Counter() {
const { state, dispatch } = useContext(AppContext);
return (
<div>
<p>شمارنده: {state.count}</p>
<button onClick={() => dispatch({ type: "increment" })}>افزایش</button>
</div>
);
}
این ساختار بهت کمک میکنه منطق تغییر state رو از نمایش UI جدا کنی
و بدون Prop Drilling در کل پروژه ازش استفاده کنی.
مزایا و نکات مهم
- جلوگیری از Prop Drilling: نیازی به ارسال props در چند سطح نداری.
- افزایش خوانایی: دادههای مشترک بهصورت مرکزی نگهداری میشن.
- ترکیبپذیری عالی: با useReducer یا useState بهراحتی میتونی contextهای مختلف بسازی.
- بهینهسازی: فقط زمانی که مقدار context تغییر کنه، کامپوننتهای مصرفکننده دوباره رندر میشن.
سوالات متداول
- چه زمانی از useContext استفاده کنم؟
-
وقتی دادهای داری که باید در چند کامپوننت استفاده بشه مثل تم، زبان، یا اطلاعات کاربر.
- آیا میتونم چند Context همزمان داشته باشم؟
-
بله، React هیچ محدودیتی نداره. میتونی Contextهای جداگانه برای تنظیمات، احراز هویت و دادهها داشته باشی.
- آیا useContext جایگزین Redux هست؟
-
در پروژههای کوچک تا متوسط، ترکیب useContext و useReducer میتونه جایگزین کاملی برای Redux باشه.
- منبع رسمی؟
-
React Docs: useContext
جمعبندی
هوک useContext راهی قدرتمند برای مدیریت دادههای مشترک در Reactه.
باهاش میتونی ساختار تمیزتر، قابلفهمتر و بدون Prop Drilling بسازی.
اگه در کنار useReducer یا useState ازش استفاده کنی،
درواقع یه سیستم مدیریت state کامل و سبک در اختیار داری که هم سئوپسند و هم توسعهپذیره.