مقدمه
تاکنون، تنها راه ما برای اشتراکگذاری داده بین کامپوننتها، ارسال props از والد به فرزند بوده
است. این روش برای کامپوننتهایی که نزدیک به هم هستند به خوبی کار میکند. اما تصور کنید یک
اپلیکیشن بزرگ دارید که در آن، یک state تعریف شده در کامپوننت سطح بالا، باید توسط یک کامپوننت
در عمق زیادی از درخت کامپوننتها استفاده شود.
در این حالت، ما مجبوریم prop را از طریق تمام کامپوننتهای میانی (که خودشان به آن prop نیازی
ندارند) عبور دهیم تا به کامپوننت مقصد برسد. به این الگوی نامطلوب، «حفاری پراپ» یا Prop
Drilling گفته میشود. این کار کد را شلوغ کرده و نگهداری آن را دشوار میکند.
راهحل: React Context
React Context API یک راه حل برای مشکل prop drilling ارائه میدهد. Context به شما اجازه
میدهد تا دادههایی را که «سراسری» (global) در نظر گرفته میشوند (مانند اطلاعات کاربر لاگین
کرده، تم اپلیکیشن، یا زبان انتخابی) را بدون نیاز به پاس دادن دستی props در هر سطح، در اختیار
تمام کامپوننتهای زیرمجموعه خود قرار دهید.
سه مرحله اصلی کار با Context
- ایجاد Context: با استفاده از createContext()، یک شیء
context ایجاد میکنیم.
- فراهم کردن Context: کامپوننتهای خود را با یک Context Provider احاطه کرده و
دادهای را که میخواهیم به اشتراک بگذاریم، به prop مربوط به value آن پاس میدهیم.
- استفاده از Context: هر کامپوننت فرزندی در این زیردرخت، میتواند با استفاده از هوک
useContext، به این داده دسترسی پیدا کند.
یک مثال کاربردی
بیایید یک مثال ساده برای مدیریت تم تیره/روشن با استفاده از Context بسازیم.
۱. ایجاد ThemeContext
ابتدا، یک فایل جدید به نام ThemeContext.js ایجاد کرده و کد زیر را در آن قرار میدهیم:
ThemeContext.js
import { createContext } from 'react';
export const ThemeContext = createContext('light');
این کد یک context جدید به نام ThemeContext ایجاد میکند که مقدار پیشفرض آن
'light' است.
۲. فراهم کردن Context در کامپوننت والد
حالا در کامپوننت اصلی اپلیکیشن (مثلاً App.js)، از ThemeContext.Provider برای
فراهم کردن مقدار تم استفاده میکنیم.
App.js
import { ThemeContext } from './ThemeContext';
import Toolbar from './Toolbar';
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
در اینجا، ما کامپوننت Toolbar (و تمام فرزندان آن) را با ThemeContext.Provider احاطه کرده و
مقدار 'dark' را به عنوان value فراهم کردهایم.
۳. استفاده از Context در کامپوننت فرزند
حالا هر کامپوننت فرزندی، هرچقدر هم که در عمق قرار داشته باشد، میتواند با هوک useContext به
این مقدار دسترسی پیدا کند.
JAVASCRIPT (React)
import { useContext } from 'react';
import { ThemeContext } from './ThemeContext';
function ThemedButton() {
const theme = useContext(ThemeContext);
return (
<button style={{ background: theme === 'dark' ? 'black' : 'white' }}>
I am styled by theme context!
</button>
);
}
کامپوننت ThemedButton با useContext(ThemeContext) نزدیکترین value فراهم شده توسط یک
Provider در بالای خود را میخواند و از آن برای استایلدهی استفاده میکند.
در این درس، با React Context به عنوان یک راهحل قدرتمند برای مشکل prop drilling آشنا شدیم.
دیدیم که چگونه میتوان با استفاده از Provider و هوک useContext دادههای سراسری را به صورت
کارآمد در اختیار یک درخت از کامپوننتها قرار داد.
Context یک ابزار عالی برای دادههایی است که به ندرت تغییر میکنند. اما اگر بخواهیم یک state
پیچیده را به همراه منطق بهروزرسانی آن به صورت سراسری به اشتراک بگذاریم چه؟ در درس بعدی، به
«ترکیب useReducer با useContext» خواهیم پرداخت و خواهیم دید که چگونه میتوان با ترکیب این دو
هوک، یک الگوی مدیریت وضعیت بسیار قدرتمند و مقیاسپذیر ایجاد کرد.