React Context: راهنمای تفصیلی

Dead Simple Chat قدرتمند ارائه می دهد JavaScript Chat API که می توانید از آن برای افزودن چت به هر React یا برنامه وب در عرض چند دقیقه استفاده کنید. Dead Simple Chat بسیار قابل تنظیم است و چت برای هر مورد استفاده از چت قابل استفاده است.
معمولاً وقتی می خواهید داده ها را از مؤلفه والد به مؤلفه های فرزند منتقل کنید، از props استفاده می کنید.
اما اگر دادهها باید عمیقاً از چندین مؤلفه منتقل شوند، وقتی چندین مؤلفه به دادههای مشابهی نیاز دارند، استفاده از props برای ارسال داده در درخت مؤلفه دشوار میشود.
زمینه می تواند به عنوان جایگزینی برای انتقال داده با استفاده از props استفاده شود. Context به مؤلفه والد اجازه می دهد تا داده ها را به کل درخت مؤلفه های فرزند زیر آن منتقل کند.
بنابراین وظیفه انتقال دستی لوازم جانبی به تمام اجزای فرزند که به داده های یکسانی نیاز دارند بسیار کاهش می یابد.
بیایید به یک مثال سریع با استفاده از React Context نگاه کنیم.
مثال زمینه واکنش سریع
ما یک برنامه React بسیار ابتدایی با استفاده از React Context ایجاد خواهیم کرد تا آن را ارسال کنیم theme
درخت جزء را پایین بیاورید.
این برنامه به کاربران اجازه می دهد تا بین تم های روشن و تاریک جابجا شوند
- ایجاد یک
ThemeProvider.jsx
فایل برای ذخیره منطق ThemeContext ما.
import { createContext, useState } from 'react';
export const ThemeContext = createContext();
const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme(theme === 'light' ? 'dark' : 'light');
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};
export default ThemeProvider;
ما استفاده کرده ایم createContext()
روشی برای ایجاد یک زمینه به نام ThemeContext
سپس یک را ایجاد می کنیم ThemeProvider
و در ThemeProvider
متد، حالت و متدهایی را که میخواهیم به همه مؤلفههای فرزند منتقل کنیم، اضافه میکنیم.
در روش بازگشت، ما در حال افشاگری هستیم theme
متغیر حالت و toggleTheme
روش به تمام اجزای فرزند با استفاده از پایه value={{ theme, toggleTheme }}
این theme
ایالت و toggleTheme
متغیر برای همه اجزای فرزند در دسترس خواهد بود.
2. وارد کنید ThemeProvider
به شما App.js
و بپیچید ThemeProvider
اطراف مولفه ریشه شما این اجازه می دهد تا تمام اجزای فرزند به Context دسترسی داشته باشند.
import React from 'react';
import ThemeProvider from './ThemeProvider';
import MainComponent from './MainComponent';
function App() {
return (
<ThemeProvider>
<MainComponent />
</ThemeProvider>
);
}
export default App;
3. حالا ما آن را ایجاد می کنیم MainComponent.js
فایل برای مصرف Context
import { useContext } from 'react';
import { ThemeContext } from './ThemeProvider';
const MainComponent = () => {
const { theme, toggleTheme } = useContext(ThemeContext);
const themeStyles = {
backgroundColor: theme === 'light' ? '#fff' : '#333',
color: theme === 'light' ? '#333' : '#fff',
};
return (
<div style={themeStyles}>
<h1>Main Component</h1>
<p>Current Theme: {theme}</p>
<button onClick={toggleTheme}>Toggle Theme</button>
</div>
);
};
export default MainComponent;
در کد بالا، ما از useContext
قلاب برای واکشی theme
متغیر حالت و toggleTheme
روش از زمینه
useContext
این useContext
روش برای استفاده از زمینه در مولفه های فرزند استفاده می شود. این useContext
متد زمینه ای را می پذیرد که مؤلفه فرزند می خواهد از آن استفاده کند و می توانیم متدها و متغیرهای در معرض دید زمینه را استخراج کنیم.
const { theme, toggleTheme } = useContext(ThemeContext);
مثال های بیشتر با استفاده از React Context
بیایید به چند مثال دیگر با استفاده از React Context و جایی که منطقی است از React Context در برنامه خود استفاده کنید نگاه کنیم.
استفاده از React Context با React Toastify
React Toastify کتابخانه ای است که برای نمایش اعلان های نان تست در برنامه شما استفاده می شود.
اگر می خواهید یک آموزش دقیق در مورد React Toastify یاد بگیرید، می توانید به پست وبلاگ راهنمای کامل React Toastify ما مراجعه کنید.
در حال حاضر، ما یک برنامه اساسی با استفاده از React Toastify ایجاد خواهیم کرد و هدف ما این است که به برنامه اجازه دهیم اعلانهای نان تست را از هر مؤلفه فعال کند.
ما میتوانیم روشی برای راهاندازی اعلان نان تست و ارسال آن به مؤلفههای فرزند ایجاد کنیم، اما وقتی درخت مؤلفه با مؤلفههای فرزند زیاد رشد میکند، این روش دست و پا گیر میشود.
برای حل این مشکل، میتوانیم یک Context ایجاد کنیم و روشی را برای نمایش اعلان نان تست در متن اضافه کنیم، و مولفههای فرزند میتوانند از متن استفاده کنند و متد را برای نمایش اعلان نان تست فراخوانی کنند.
- ابتدا ما آن را نصب می کنیم
react-toastify
بسته بندی
npm install --save react-toastify
2. در ادامه یک فایل به نام as ایجاد می کنیم ToastProvider.js
این فایل حاوی ما خواهد بود ToastContext
و ToastProvider
import { createContext } from "react";
import { toast } from "react-toastify";
export const ToastContext = createContext();
const ToastProvider = ({ children }) => {
const showToast = (message, type) => {
toast[type](message);
};
return (
<ToastContext.Provider value={{ showToast }}>
{children}
</ToastContext.Provider>
);
};
export default ToastProvider;
3. بپیچید ToastProvider
اطراف مولفه Root در شما App.js
فایل
import React from 'react';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import ToastProvider from './ToastProvider';
import MainComponent from './MainComponent';
function App() {
return (
<ToastProvider>
<MainComponent />
<ToastContainer />
</ToastProvider>
);
}
export default App;
3. ایجاد کنید MainComponent.js
فایل برای ذخیره MainComponent
. در MainComponent
ما از زمینه برای فعال کردن اعلان نان تست استفاده خواهیم کرد
import { useContext } from "react";
import ChildComponent from "./ChildComponent";
import { ToastContext } from "./ToastProvider";
const MainComponent = () => {
const { showToast } = useContext(ToastContext);
const handleShowToast = (type) => {
const message = `This is a ${type} toast!`;
showToast(message, type);
};
return (
<div>
<h1>Main Component</h1>
<button onClick={() => handleShowToast("success")}>
Show Success Toast
</button>
<button onClick={() => handleShowToast("error")}>Show Error Toast</button>
<ChildComponent />
</div>
);
};
export default MainComponent;
4. یک کامپوننت به نام the ایجاد کنید ChildComponent.js
این به ما امکان می دهد از Context در Child Component نیز استفاده کنیم
import { useContext } from "react";
import AnotherChildComponent from "./AnotherChildComponent";
import { ToastContext } from "./ToastProvider";
function ChildComponent() {
const { showToast } = useContext(ToastContext);
function triggerToast() {
showToast("Toast tiggered from child component", "success");
}
return (
<div>
<h1>Child Componenet</h1>
<button
onClick={() => {
triggerToast();
}}
>
Trigger Toast
</button>
<AnotherChildComponent />
</div>
);
}
export default ChildComponent;
5. ما مؤلفه های بیشتری را که فرزند «ChildComponent» نامیده می شود، خواهیم کرد AnotherChildComponent.js
import { useContext } from "react";
import { ToastContext } from "./ToastProvider";
function AnotherChildComponent() {
const { showToast } = useContext(ToastContext);
function triggerToast() {
showToast("Toast tiggered from AnotherChild component", "success");
}
return (
<div>
<h1>Another Child Componenet</h1>
<button
onClick={() => {
triggerToast();
}}
>
Trigger Toast
</button>
</div>
);
}
export default AnotherChildComponent;
در اینجا کد کاملی است که CodeSandbox را اجرا می کند:
%[https://codesandbox.io/s/dazzling-murdock-zig94y?from-embed]
مثال با زمینه های چندگانه
حال بیایید به مثالی نگاه کنیم که از چندین React Context استفاده می کند. با استفاده از یک React Application چند صفحه ای ایجاد خواهیم کرد react-router-dom
و دو Context ایجاد می کند که یکی آن خواهد بود ThemeContext
برای مدیریت موضوع و یکی دیگر خواهد بود UserContext
.
-
با استفاده از یک برنامه react جدید ایجاد کنید
create-react-app
npx create-react-app multi-context-app cd multi-context-app
-
اکنون نصب کنید
react-router-dom
بسته، که به ما امکان می دهد مسیریابی را در برنامه خود ایجاد کنیمnpm install react-router-dom
-
اکنون ما خود را ایجاد خواهیم کرد
ThemeContext
. یک پوشه به نام contexts در داخل پوشه src ایجاد کنید و در آنجا یک فایل به نام ایجاد کنیدThemeContext.js
// src/contexts/ThemeContext.js import { createContext, useState } from "react"; const ThemeContext = createContext(); const ThemeProvider = ({ children }) => { const [theme, setTheme] = useState("light"); const toggleTheme = () => { setTheme(theme === "light" ? "dark" : "light"); }; return ( <ThemeContext.Provider value={{ theme, toggleTheme }}> {children} </ThemeContext.Provider> ); }; export { ThemeContext, ThemeProvider };
این
ThemeContext
شبیه ThemeContext است که در اولین مثال خود ایجاد کرده ایم. -
بعد زمینه دیگری به نام the ایجاد کنید
UserContext
، داخل پوشه contexts ما. اینUserContext
اطلاعات مربوط به کاربر وارد شده را نگه می دارد.
// src/contexts/UserContext.js
import { createContext, useState } from "react";
const UserContext = createContext();
const UserProvider = ({ children }) => {
const [user, setUser] = useState(null);
const login = (username, password) => {
// perform login logic and set the user object
setUser({ username, email: "user@example.com" });
};
const logout = () => {
// perform logout logic and set the user object to null
setUser(null);
};
return (
<UserContext.Provider value={{ user, login, logout }}>
{children}
</UserContext.Provider>
);
};
export { UserContext, UserProvider };
ما مولفه هایی ایجاد خواهیم کرد که از زمینه استفاده می کنند.
ایجاد خواهیم کرد Header
مؤلفه ای که تم فعلی را نمایش می دهد و به کاربر اجازه می دهد آن را تغییر دهد و ما نیز a ایجاد می کنیم Profile
مؤلفه ای که اطلاعات کاربر وارد شده فعلی را نشان می دهد و همچنین به آنها امکان خروج از سیستم را می دهد.
شاید قبلا حدس زده باشید، Header
جزء استفاده خواهد کرد ThemeContext
و Profile
جزء استفاده می کند UserContext
.
- یک فایل به نام ایجاد کنید
src/Header.js
این کامپوننت هدر ما را نگه می دارد و کد زیر را به آن فایل اضافه می کند:
// src/Header.js
import { useContext } from "react";
import { ThemeContext } from "./contexts/ThemeContext";
import { Link } from "react-router-dom";
const Header = () => {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<header className={`header ${theme}`}>
<button onClick={toggleTheme}>Toggle Theme</button>
<nav>
<ul style={{ listStyle: "none" }}>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/dashboard">Dashboard</Link>
</li>
</ul>
</nav>
</header>
);
};
export default Header;
در کد بالا، ما از ThemeContext
و اطلاعات تم فعلی را دریافت کنید و موضوع فعلی را به عنوان className
برای سربرگ
ما همچنین تماس می گیریم toggleTheme
روشی که توسط ThemeContext
زمانی که کاربر روی Toggle Theme
دکمه.
-
فایل دیگری به نام as ایجاد کنید
src/Profile.js
این کد را برای ما نگه می داردProfile
جزء.// src/Profile.js import { useContext } from "react"; import { UserContext } from "./contexts/UserContext"; const Profile = () => { const { user, login, logout } = useContext(UserContext); const handleLogin = () => { login("myusername", "mypassword"); }; const handleLogout = () => { logout(); }; return ( <div className="profile"> {user ? ( <> <h2>{user.username}</h2> <p>{user.email}</p> <button onClick={handleLogout}>Logout</button> </> ) : ( <> <button onClick={handleLogin}>Login</button> </> )} </div> ); }; export default Profile;
این
Profile
جزء استفاده می کندUserContext
. ما ورود و خروج را ساده کرده ایم و اطلاعات کاربر را نمایش خواهیم داد. در کامپوننت پروفایل، دکمههای ورود و خروج را نیز اضافه کردهایم که با فشار دادن آنها متدهای Context را برای شبیهسازی ورود و خروج فراخوانی میکنند. -
حال اجازه دهید مسیریابی را در برنامه خود راه اندازی کنیم و دو صفحه ایجاد کنیم
Home
وDashboard
که از ما استفاده خواهد کردHeader
وProfile
اجزاء.یک فایل به نام as ایجاد کنید
src/Home.js
که صفحه اصلی ما را نگه می دارد.
// src/Home.js
import React from "react";
import Profile from "./Profile";
const Home = () => {
return (
<div className="home">
<h2>Welcome to My App</h2>
<p>This is the home page of my app</p>
<Profile />
</div>
);
};
export default Home;
این Home
مؤلفه از مؤلفه Profile برای نمایش اطلاعات نمایه استفاده می کند.
فایل دیگری به نام as ایجاد کنید Dashboard.js
این مسیر داشبورد را نشان می دهد.
// src/Dashboard.js
import { useContext } from "react";
import { UserContext } from "./contexts/UserContext";
const Dashboard = () => {
const { user, login, logout } = useContext(UserContext);
function handleLogin() {
login("username", "password");
}
return (
<div className="dashboard">
{user ? (
<>
<h2>Dashboard</h2>
<p>Welcome to your dashboard, {user.username}</p>
</>
) : (
<>
<p>You need to be logged in to access the dashboard</p>
<button onClick={handleLogin}>Login</button>
</>
)}
</div>
);
};
export default Dashboard;
در Dashboard
جزء ما مستقیماً از زمینه برای واکشی اطلاعات کاربر استفاده میکنیم، و همچنین یک دکمه ورود به سیستم اضافه کردهایم تا به کاربر اجازه ورود به سیستم را بدهد، اگر کاربر وارد نشده باشد.
- فایل App.js را برای وارد کردن ارائه دهندگان، هدر و روترها به روز کنید
// src/App.js
import React from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import Header from "./Header";
import Home from "./Home";
import Dashboard from "./Dashboard";
import { ThemeProvider } from "./contexts/ThemeContext";
import { UserProvider } from "./contexts/UserContext";
import "./App.css";
const App = () => {
return (
<Router>
<ThemeProvider>
<UserProvider>
<div className="App">
<Header />
<Routes>
<Route exact path="/" element={<Home />} />
<Route exact path="/dashboard" element={<Dashboard />} />
</Routes>
</div>
</UserProvider>
</ThemeProvider>
</Router>
);
};
export default App;
در اینجا کد کامل در حال اجرا در Code Sandbox است:
%[https://codesandbox.io/s/reverent-rumple-o1pdv6?from-embed]
اکنون یک مثال جامع با استفاده از React Context دیدهایم، اکنون اجازه میدهیم در مورد اینکه کجا استفاده از React Context منطقی است و در چه سناریوهایی باید از React Context اجتناب شود، بحث کنیم.
سناریوهایی برای استفاده از React Context
React context به ویژه زمانی مفید است که یک حالت جهانی در سراسر برنامه وجود داشته باشد که باید با بسیاری از مؤلفه ها به اشتراک گذاشته شود. در اینجا برخی از سناریوهایی وجود دارد که در آنها استفاده از React Context منطقی است.
-
مدیریت دولت جهانی: وقتی یک حالت جهانی دارید که باید بین بسیاری از مؤلفهها به اشتراک گذاشته شود، مانند تم، سفارشیسازی، پیکربندی برنامه، تأیید هویت کاربر و غیره، پس React Context انتخاب خوبی است.
-
جلوگیری از حفاری پایه: نمونه ها را هم بحث کرده ایم و دیده ایم. هنگامی که شما نیاز به انتقال داده از طریق چندین مؤلفه دارید، انتقال داده ها از طریق props بسیار دشوار است. با استفاده از React Context، میتوانید دادهها را بهطور تمیز از درخت مؤلفه خود عبور دهید و در نتیجه کد قابل نگهداری به دست آورید.
-
اضافه کردن قابلیت استفاده مجدد به کد: با React Context می توانید منطق را مجدداً در برنامه خود استفاده کنید. همانطور که در مثال زیر دیدیم، ما از React Context برای راهاندازی Toast استفاده میکنیم تا اعلانها را از هر نقطه در درخت کامپوننت نشان دهیم.
توجه به این نکته ضروری است که نباید بیش از حد از Context استفاده کنید. همانطور که در اسناد واکنش رسمی ذکر شده است که “فقط به این دلیل که شما نیاز دارید که برخی از وسایل را در چندین سطح عمیق بگذرانید، به این معنی نیست که باید آن اطلاعات را در متن قرار دهید.”
ابتدا با عبور دادن props به سمت پایین شروع کنید و اگر خیلی دست و پا گیر شد، آن را با استفاده از React Context تغییر دهید.
عبور دادن پایه ها به پایین ترجیح داده می شود زیرا سطحی از شفافیت را در پایگاه کد اضافه می کند.
علاوه بر این، اگر برنامه شما به مدیریت پیچیده ایالت نیاز دارد، ممکن است از یک کتابخانه مدیریت دولتی اختصاصی مانند Redux یا MobX استفاده کنید.
سناریوهایی برای عدم استفاده از React Context
در اینجا برخی از سناریوهایی وجود دارد که باید از استفاده از React Context اجتناب کنید.
-
ایالت مرتبط محلی: هنگامی که حالت فقط به چند مؤلفه نزدیک مرتبط است، استفاده از React Context بسیار زیاد است و باعث ایجاد پیچیدگی غیر ضروری می شود.
-
وضعیت بهروزرسانی مکرر: React context همه مؤلفهها را با استفاده از حالت دوباره رندر میکند. اگر یک مقدار حالت به طور مکرر به روز شود و به همه مؤلفه ها مربوط نباشد، باعث مشکلات عملکرد و رندر مجدد غیرضروری مؤلفه ها می شود.
-
مدیریت مجتمع دولتی: زمینه React برای مدیریت حالت جهانی ساده مناسب است. اگر برنامه شما به مدیریت وضعیت پیچیده و ویژگی های پیشرفته نیاز دارد، استفاده از چیزی مانند Redux یا MobX منطقی تر خواهد بود.
-
ارتباط جزء به جزء: اگر می خواهید دو مؤلفه فرزند با یکدیگر ارتباط برقرار کنند، پس زمینه React انتخاب خوبی نیست. در این حالت، می توانید وضعیت را بالا ببرید یا عملکردهای برگشت به تماس را ارسال کنید.
-
ساختارهای داده پیچیده: React Context برای ساختارهای داده مسطح مناسب است. اگر وضعیت شما به یک ساختار داده تودرتو پیچیده نیاز دارد، پس زمینه React ممکن است بهترین انتخاب نباشد و حفظ آن دشوار است و منجر به مشکلات عملکرد می شود.
React Context Pitfalls
هنگام استفاده از React Context در اینجا برخی از مشکلات وجود دارد که باید از آنها آگاه باشید تا از مشکلات عملکرد، تنگناها و ایجاد کدهایی که نگهداری آنها سخت است جلوگیری کنید.
-
استفاده بیش از حد از زمینه: استفاده بیش از حد از React Context و حتی React State آسانتر است. افزودن زمینه جدید و حتی وضعیت جدید به برنامه پیچیدگی میافزاید، بنابراین هنگام استفاده از React Context باید مراقب باشید و در مواقع ضروری آن را به برنامه خود اضافه کنید.
-
اتصال محکم قطعات: استفاده بیش از حد از Context در برنامه شما منجر به ایجاد کامپوننت هایی می شود که به شدت با یکدیگر مرتبط هستند و به روز رسانی یک جزء منجر به عوارض جانبی غیرضروری در سایر اجزا می شود. برای جلوگیری از این اجزای طراحی با یک مرز مشخص.
-
مقادیر متن قابل تغییر: هرگز مقادیر متن را مستقیماً به روز نکنید، همیشه از آن استفاده کنید
setState
روش یا روشی در ارائهدهنده زمینه برای بهروزرسانی وضعیت ایجاد کنید. به روز رسانی مقدار متن به طور مستقیم منجر به رفتار غیرمنتظره و یافتن اشکالات سخت می شود. -
رندرهای غیر ضروری: هنگامی که یک مقدار زمینه تغییر می کند، همه مؤلفه هایی که زمینه را مصرف می کنند دوباره رندر می شوند، این می تواند منجر به مشکلات عملکرد زمانی شود که بسیاری از مؤلفه ها از زمینه استفاده می کنند. از این رو، زمانی که مقدار آن به طور مکرر تغییر می کند، نباید از متن استفاده کنید یا باید زمینه را تقسیم کنید و فقط مؤلفه های مرتبط باید زمینه را که اغلب به روز می شوند مصرف کنند.
نتیجه
در این راهنما، React Context API را بررسی کردهایم و نمونههای سادهتر و همچنین پیچیدهتری را مشاهده کردهایم که از زمینههای متعدد استفاده میکنند.
ما همچنین در مورد سناریوهایی که در آن استفاده از React Context منطقی است، و جایی که باید از آن اجتناب کرد، بحث کردهایم و همچنین به برخی از مشکلات هنگام استفاده از React Context اشاره کردهایم.
امیدوارم این راهنما به شما درک خوبی از React Context بدهد.
این مقاله در ابتدا در وبلاگ DeadSimpleChat منتشر شد: React Context: The Detailed Guide