مقدمة لواجهة برمجة تطبيقات سياق React
نشرت: 2022-03-10في هذا البرنامج التعليمي ، يجب أن يكون لديك فهم جيد للخطافات. ومع ذلك ، قبل أن نبدأ ، سأناقش بإيجاز ماهيتهم والخطافات التي سنستخدمها في هذه المقالة.
وفقًا لـ React Docs:
" الخطافات هي إضافة جديدة في React 16.8. إنها تتيح لك استخدام ميزات الحالة وميزات React الأخرى دون كتابة فصل دراسي. "
هذا هو أساسًا ما هو خطاف React. يسمح لنا باستخدام الحالة والمراجع وميزات React الأخرى في مكوناتنا الوظيفية.
دعونا نناقش الخطافين اللذين سنواجههما في هذه المقالة.
خطاف useState
يسمح لنا الخطاف useState باستخدام الحالة في مكوناتنا الوظيفية. يأخذ الخطاف useState
القيمة الأولية لحالتنا على أنها الوسيطة الوحيدة ، ويعيد مصفوفة من عنصرين. العنصر الأول هو متغير الحالة الخاص بنا والعنصر الثاني هو وظيفة يمكننا من خلالها استخدام تحديث قيمة متغير الحالة.
دعنا نلقي نظرة على المثال التالي:
import React, {useState} from "react"; function SampleComponent(){ const [count, setCount] = useState(0); }
هنا ، count
هو متغير الحالة الخاص بنا وقيمته الأولية هي 0
بينما setCount
هي وظيفة يمكننا استخدامها لتحديث قيمة count.
خطاف useContext
سأناقش هذا لاحقًا في المقالة ولكن هذا الخطاف يسمح لنا أساسًا باستهلاك قيمة السياق. ما يعنيه هذا في الواقع سيصبح أكثر وضوحًا لاحقًا في المقالة.
مساحات عمل الغزل
تتيح لك مساحات عمل الغزل تنظيم قاعدة كود مشروعك باستخدام مستودع متآلف (monorepo). React هو مثال جيد لمشروع مفتوح المصدر monorepo ويستخدم مساحات عمل Yarn لتحقيق هذا الغرض. اقرأ مقالًا ذا صلة ←
لماذا نحتاج إلى سياق API؟
نريد إنشاء مكون "theme toggler" يقوم بالتبديل بين الوضع الفاتح والوضع المظلم لتطبيق React الخاص بنا. يجب أن يكون لكل مكون إمكانية الوصول إلى وضع السمة الحالي حتى يمكن تصميمه وفقًا لذلك.
عادةً ، نوفر وضع السمة الحالي لجميع المكونات من خلال الدعائم وتحديث السمة الحالية باستخدام state
:
import React from "react"; import ReactDOM from "react-dom"; function App() { return ( <div> <Text theme= "blue" /> <h1>{theme}</h1> </div> ); } function Text({theme}) { return( <h1 style = {{ color: `${theme}` }}>{theme}</h1> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
في نموذج الكود أعلاه ، أنشأنا مكونًا نصيًا يعرض عنصر h1
. يعتمد لون عنصر h1
على وضع السمة الحالي. حاليًا ، الموضوع باللون الأزرق. يمكننا التبديل بين السمات blue
red
باستخدام state
.
سننشئ حالة تسمى "theme" باستخدام الخطاف useState
. سيعيد الخطاف useState
القيمة الحالية للموضوع والوظيفة التي يمكننا استخدامها لتحديث السمة.
لذلك ، دعونا ننشئ حالة الموضوع الخاصة بنا:
const [theme, setTheme] = React.useState("blue");
سنضيف أيضًا عنصر زر إلى مكون App
الخاص بنا. سيتم استخدام هذا الزر لتبديل السمات ويحتاج إلى معالج حدث نقرة. لذا ، دعنا نكتب معالج حدث click كما يلي:
const onClickHandler = () => { setTheme(); }
الآن ، نريد تعيين السمة الجديدة إلى Red
إذا كان السمة الحالية هي Blue
، والعكس صحيح. بدلاً من استخدام تعليمة if
، فإن الطريقة الأكثر ملاءمة للقيام بذلك هي بمساعدة العامل الثلاثي في JavaScript.
setTheme( theme === "red"? "blue": "red");
الآن ، قمنا بكتابة معالج onClick
بنا. دعنا نضيف عنصر الزر هذا إلى مكون App
:
<button onClick = {onClickHandler}>Change theme</button>
دعونا أيضًا نغير قيمة دعائم السمة لمكون النص إلى حالة السمة.
<Text theme={theme}/>
الآن ، يجب أن يكون لدينا هذا:
import React from "react"; import ReactDOM from "react-dom"; import "./styles.css"; function App() { const[theme, setTheme] = React.useState("red"); const onClickHandler = () => { setTheme( theme === "red"? "blue": "red"); } return ( <div> <Text theme={theme}/> <button onClick = {onClickHandler}>Change theme</button> </div> ); } function Text({theme}) { return( <h1 style = {{ color: `${theme}` }}>{theme}</h1> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
يمكننا الآن التبديل بين الموضوعين. ومع ذلك ، إذا كان هذا تطبيقًا أكبر بكثير ، فسيكون من الصعب استخدام السمة في مكونات متداخلة بشدة وتصبح الشفرة غير عملية.
تقديم سياق API
اسمحوا لي أن أقدم واجهة برمجة تطبيقات السياق. وفقًا لوثائق React:
"يوفر السياق طريقة لتمرير البيانات عبر شجرة المكونات دون الحاجة إلى تمرير الخاصيات يدويًا على كل مستوى."
للحصول على تعريف أكثر تعمقًا ، يوفر لك طريقة لإتاحة بيانات معينة لجميع المكونات في جميع أنحاء شجرة المكونات بغض النظر عن مدى عمق هذا المكون.
دعونا نلقي نظرة على هذا المثال:
const App = () => { return( <ParentComponent theme = "light"/> ); } const ParentComponent = (props) => ( <Child theme = {props.theme} /> ) const Child = (props) => ( <Grandchild theme = {props.theme} /> ) const Grandchild = (props) => ( <p>Theme: {props.theme}</p> )
في المثال أعلاه ، حددنا سمة التطبيق باستخدام الخاصيات في ParentComponent
المسمى theme
. كان علينا أن نمرر هذه الدعائم إلى جميع المكونات أسفل شجرة المكونات لنحصل عليها في المكان المطلوب وهو مكون GrandChild
. لم يكن ChildComponent
أي علاقة بدعائم السمة ولكنه استخدم فقط كوسيط.
الآن ، تخيل أن مكون GrandChild
كان متداخلًا بشكل أعمق مما كان عليه في المثال العلوي. سيتعين علينا تمرير دعائم السمة بنفس الطريقة التي فعلنا بها هنا والتي ستكون مرهقة. هذه هي المشكلة التي يحلها Context
. باستخدام Context
، يتمتع كل مكون في شجرة المكونات بإمكانية الوصول إلى أي بيانات نقرر وضعها في سياقنا.
لنبدأ مع Context
حان الوقت لتكرار زر تبديل السمة الذي أنشأناه في بداية المقالة باستخدام واجهة برمجة تطبيقات السياق. هذه المرة ، سيكون مفتاح تبديل السمة مكونًا منفصلاً. سنقوم ببناء مكون ThemeToggler
الذي يقوم بتبديل سمة تطبيق React الخاص بنا باستخدام Context
.
أولاً ، دعونا نبدأ تطبيق React الخاص بنا. (أنا أفضل استخدام create-react-app
ولكن يمكنك استخدام أي طريقة تفضلها.)
بمجرد بدء مشروع React الخاص بك ، قم بإنشاء ملف يسمى ThemeContext.js في مجلد /src
الخاص بك. يمكنك أيضًا إنشاء مجلد يسمى /context
ووضع ملف ThemeContext الخاص بك هناك إذا كنت تريد ذلك.
الآن ، دعونا ننتقل.
إنشاء سياق API الخاص بك
سننشئ سياق موضوعنا في ملف ThemeContext.js الخاص بنا.
لإنشاء سياق ، نستخدم React.createContext
الذي ينشئ كائن سياق. يمكنك تمرير أي شيء كوسيطة لـ React.createContext
. في هذه الحالة ، سنقوم بتمرير سلسلة وهي وضع السمة الحالي. حتى الآن وضع السمة الحالي لدينا هو وضع السمة "الخفيفة".
import React from "react"; const ThemeContext = React.createContext("light"); export default ThemeContext;
لجعل هذا السياق متاحًا لجميع مكونات React الخاصة بنا ، يتعين علينا استخدام مزود. ما هو المزود؟ وفقًا لوثائق React ، يأتي كل كائن سياق مع مكون Provider React الذي يسمح باستهلاك المكونات للاشتراك في تغييرات السياق. هو الموفر الذي يسمح للمكونات الأخرى باستهلاك السياق. ومع ذلك ، دعونا ننشئ مزودنا.
انتقل إلى ملف App.js الخاص بك. من أجل إنشاء مزودنا ، يتعين علينا استيراد ThemeContext
الخاص بنا.
بمجرد استيراد ThemeContext
، يتعين علينا إرفاق محتويات مكون App
الخاص بنا في علامات ThemeContext.Provider
وإعطاء مكون ThemeContext.Provider
تسمى value
والتي ستحتوي على البيانات التي نريد إتاحتها لشجرة المكونات الخاصة بنا.
function App() { const theme = "light"; return ( <ThemeContext.Provider value = {theme}> <div> </div> </ThemeContext.Provider> ); }
والآن أصبحت قيمة "light" متاحة لجميع مكوناتنا (والتي سنكتبها قريبًا).
إنشاء ملف موضوعنا
الآن ، سننشئ ملف السمة الخاص بنا والذي سيحتوي على قيم الألوان المختلفة لكل من السمات الفاتحة والداكنة. قم بإنشاء ملف في مجلد /src
يسمى Colors.js .
في Colors.js ، سننشئ كائنًا يسمى AppTheme
. سيحتوي هذا الكائن على ألوان موضوعاتنا. بمجرد الانتهاء ، قم بتصدير كائن AppTheme
مثل:
const AppTheme = { light: { textColor: "#000", backgroundColor: "#fff" }, dark: { textColor: "#fff", backgroundColor: "#333" } } export default AppTheme;
حان الوقت الآن لبدء إنشاء مكونات React المختلفة.
إنشاء مكونات رد الفعل لدينا
لنقم بإنشاء المكونات التالية:

-
Header
-
ThemeToggler
-
MainWithClass
Header.jsx
import React from "react"; import ThemeToggler from "./ThemeToggler"; const headerStyles = { padding: "1rem", display: "flex", justifyContent: "space-between", alignItems: "center" } const Header = () => { return( <header style = {headerStyles}> <h1>Context API</h1> <ThemeToggler /> </header> ); } export default Header;
ThemeToggler.jsx
(في الوقت الحالي ، سنعيد فقط div
فارغًا.)
import React from "react"; import ThemeContext from "../Context/ThemeContext"; const themeTogglerStyle = { cursor: "pointer" } const ThemeToggler = () => { return( <div style = {themeTogglerStyle}> </div> ); } export default ThemeToggler;
استهلاك السياق مع المكونات المستندة إلى الفئة
هنا ، سوف نستخدم قيمة ThemeContext
الخاصة بنا. كما تعلم بالفعل ، لدينا طريقتان لكتابة المكونات في React : من خلال الدوال أو الأصناف. تختلف عملية سياق الاستخدام في كلتا الطريقتين ، لذا سننشئ مكونين ليكونا بمثابة القسم الرئيسي لتطبيقنا: MainWithClass
و MainWithFunction
.
لنبدأ بـ MainWithClass
.
MainWithClass.jsx
سيتعين علينا استيراد ThemeContext
و AppTheme
. بمجرد الانتهاء من ذلك ، سنكتب فئة تُرجع JSX من طريقة تصيير. الآن علينا أن نستهلك سياقنا. هناك طريقتان للقيام بذلك مع المكونات المستندة إلى الفئة:
- الطريقة الأولى هي من خلال
Class.contextType
.
لاستخدام هذه الطريقة ، نقوم بتعيين كائن السياق منThemeContext
الخاص بنا إلى خاصيةcontextType
. بعد ذلك ، سنتمكن من الوصول إلى قيمة السياق باستخدامthis.context
. يمكنك أيضًا الرجوع إلى هذا في أي من طرق دورة الحياة وحتى طريقة العرض.import React, { Component } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; class Main extends Component{ constructor(){ super(); } static contextType = ThemeContext; render(){ const currentTheme = AppTheme[this.context]; return( <main></main> ); } }
بعد تعيينThemeContext
لخاصيةcontextType
، قمت بحفظ كائن النسق الحالي في المتغيرcurrentTheme
.
الآن ، سنلتقط الألوان من المتغيرcurrentTheme
بعض العلامات.render() { const currentTheme = AppTheme[this.context]; return ( <main style={{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main>
هذا هو! ومع ذلك ، فإن هذه الطريقة تقيدك باستهلاك سياق واحد فقط. - الطريقة الثانية هي
ThemeContext.Consumer
التي تتضمن استخدام المستهلك. يأتي كل كائن سياق أيضًا مع مكون Consumer React والذي يمكن استخدامه في مكون قائم على الطبقة. يأخذ مكون المستهلك الطفل كدالة وتعيد هذه الوظيفة عقدة React. يتم تمرير قيمة السياق الحالي إلى هذه الوظيفة كوسيطة.
الآن ، دعنا نستبدل الكود الموجود في مكونMainWithClass
بنا بهذا:class Main extends Component { constructor() { super(); this.state = { } } render(){ return( <ThemeContext.Consumer> { (theme) => { const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ) } } </ThemeContext.Consumer> ); } }
كما ترى ، استخدمنا القيمة الحالية لـThemeContext
الخاصة بنا والتي أطلقنا عليها اسم "theme" وأخذنا قيم اللون لوضع السمة هذا وقمنا بتعيينه إلى المتغيرcurrentTheme
. باستخدام هذه الطريقة ، يمكنك استخدام مستهلكين متعددين.
هاتان هما طريقتان لاستهلاك السياق مع المكونات المستندة إلى الطبقة.
استهلاك السياق مع المكونات الوظيفية
يعد استهلاك السياق بمكونات وظيفية أسهل وأقل مللاً من القيام بذلك باستخدام المكونات المستندة إلى الفصل. لاستهلاك السياق في مكون وظيفي ، سنستخدم خطافًا يسمى useContext
.
إليك ما سيبدو عليه استهلاك ThemeContext
مع مكون وظيفي:
const Main = () => { const theme = useContext(ThemeContext); const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ); } export default Main;
كما ترى ، كل ما كان علينا فعله هو استخدام خطاف useContext
بنا مع إدخال ThemeContext
كوسيطة.
ملاحظة : يجب عليك استخدام هذه المكونات المختلفة في ملف App.js لمشاهدة النتائج.
تحديث موضوعنا مع مكون ThemeToggler
الآن سنعمل على مكون ThemeToggler
الخاص بنا. نحن بحاجة إلى أن نكون قادرين على التبديل بين المظاهر الفاتحة والداكنة. للقيام بذلك ، سنحتاج إلى تعديل ThemeContext.js الخاص بنا. React.createContext
الآن كائنًا يشبه نتيجة خطاف useState
كوسيطة.
const ThemeContext = React.createContext(["light", () => {}]);
لقد مررنا مصفوفة إلى دالة React.createContext
. العنصر الأول في المصفوفة هو وضع السمة الحالي والعنصر الثاني هو الوظيفة التي سيتم استخدامها لتحديث السمة. كما قلت ، هذا يشبه نتيجة خطاف useState
ولكنه ليس نتيجة لخطاف useState
.
الآن سنقوم بتحرير ملف App.js الخاص بنا. نحتاج إلى تغيير القيمة التي تم تمريرها إلى المزود إلى خطاف useState
. الآن قيمة سياق الموضوع لدينا هي خطاف useState
قيمته الافتراضية هي "light".
function App() { const themeHook = useState("light"); return ( <ThemeContext.Provider value = {themeHook}> <div> <Header /> <Main /> </div> </ThemeContext.Provider> ); }
كتابة مكون ThemeToggler
الخاص بنا
دعنا نكتب الآن مكون ThemeToggler
بنا:
import React,{useContext} from "react"; import ThemeContext from "../Context/ThemeContext"; const themeTogglerStyle = { cursor: "pointer" } const ThemeToggler = () => { const[themeMode, setThemeMode] = useContext(ThemeContext); return( <div style = {themeTogglerStyle} onClick = {() => {setThemeMode(themeMode === "light"? "dark": "light")}}> <span title = "switch theme"> {themeMode === "light" ? "" : "️"} </span> </div> ); } export default ThemeToggler;
نظرًا لأن قيمة سياق القالب الخاص بنا أصبحت الآن خطافًا عندما نسميها useContext
، فستعيد مصفوفة. باستخدام التدمير ، تمكنا من انتزاع العناصر من المصفوفة. ثم كتبنا معالج حدث onClick
لـ ThemeToggler
الخاص بنا. باستخدام هذا الرمز ، كلما تم النقر فوق مفتاح تبديل السمة ، فإنه سيتم تبديل سمة تطبيقنا.
سنقوم الآن بتحرير الإصدارات المختلفة من المكون Main
الخاص بنا.
تحرير مكون MainWithClass
الخاص بنا
- إصدار مكون
MainWithClass
الذي يستخدم الأسلوبClass.contextType
:import React, { Component } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; class Main extends Component{ constructor(){ super(); } static contextType = ThemeContext; render(){ const currentTheme = AppTheme[this.context[0]]; return( <main style={{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ); } }
- إصدار مكون
MainWithClass
الذي يستخدم طريقةThemeContext.Consumer
:import React, { Component } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; class Main extends Component { constructor() { super(); this.state = {} } render() { return ( <ThemeContext.Consumer> { ([theme]) => { const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ) } } </ThemeContext.Consumer> ); } } export default Main;
تحرير MainWithFunction
يجب تحرير مكون MainWithFunction
على النحو التالي:
import React, { useContext } from "react"; import ThemeContext from "../Context/ThemeContext"; import AppTheme from "../Colors"; const Main = () => { const theme = useContext(ThemeContext)[0]; const currentTheme = AppTheme[theme]; return( <main style = {{ padding: "1rem", backgroundColor: `${currentTheme.backgroundColor}`, color: `${currentTheme.textColor}`, }}> <h1>Heading 1</h1> <p>This is a paragraph</p> <button> This is a button</button> </main> ); } export default Main;
خاتمة
هذا هو! لقد نجحنا في تنفيذ وضعي موضوع لتطبيق React الخاص بنا باستخدام واجهة برمجة تطبيقات السياق.
في هذه العملية ، تعلمنا:
- ما هي واجهة برمجة تطبيقات السياق والمشكلة التي تحلها ؛
- متى تستخدم سياق API ؛
- خلق
Context
واستهلاكه في كل من المكونات الوظيفية والصنفية.
مزيد من القراءة على SmashingMag:
- التصميم في تطبيقات الويب الحديثة
- بناء تطبيقات الموبايل مع Ionic و React
- بناء PWA مع Webpack و Workbox
- التعرف على واجهة برمجة تطبيقات MutationObserver