ממשק ה- API של ההקשר של React הפך לכלי ניהול המדינה הנבחר עבור רבים, ולעתים קרובות מחליף את Redux לחלוטין. במדריך מהיר זה בן 5 דקות, תראה מבוא מהו הקשר וכיצד להשתמש בו!
אם אתה רוצה היכרות מתאימה לנושא זה, תוכל להצטרף לרשימת ההמתנה לקורס ה- React המתקדם הקרוב, או אם אתה עדיין מתחיל, עיין בקורס ההיכרות החינמי שלי בנושא React.
שקול עץ זה, שבו התיבות התחתונות מייצגות רכיבים נפרדים:
אנו יכולים להוסיף בקלות מצב לרכיבים התחתונים, אך עד כה הדרך היחידה להעביר נתונים לאחיו של רכיב הייתה להעביר את המצב לרכיב גבוה יותר ואז להעביר אותו חזרה לאח באמצעות אביזרים.
אם נגלה אחר כך שאחיו של הרכיב עם המדינה זקוק גם לנתונים, עלינו להרים את המצב שוב ולהעביר אותו בחזרה למטה:
אמנם פתרון זה אכן עובד, אך הבעיות מתחילות אם רכיב בענף אחר זקוק לנתונים:
במקרה זה, עלינו להעביר מצב מהרמה העליונה של היישום דרך כל מרכיבי הביניים לזה שזקוק לנתונים בתחתית, למרות שרמות הביניים אינן זקוקות לכך. תהליך מייגע וגוזל זמן זה מכונה קידוח אביזרים .
כאן נכנס Context API. הוא מספק דרך להעביר נתונים דרך עץ הרכיב דרך צמד ספקים-צרכנים מבלי להעביר אביזרים בכל רמה. תחשוב על זה כעל הרכיבים שמשחקים Catch with data - ייתכן ורכיבי המתווך לא "יודעים" שמשהו קורה:
כדי להדגים זאת, ניצור את תמונת המעבר הפנקית (והשימושית במיוחד) הזו מהלילה.
אם אתה רוצה לראות את הקוד המלא, הקפד לבדוק את מגרש המשחקים Scrimba עבור מאמר זה.
צור הקשר
כדי להתחיל, אנו יוצרים הקשר חדש. מכיוון שאנחנו רוצים שלכל האפליקציה תהיה גישה לכך, אנחנו הולכים index.js
ועוטפים את האפליקציה ThemeContext.Provider
.
אנו מעבירים גם את value
האביזר לספק שלנו. זה מכיל את הנתונים שאנחנו רוצים לשמור. לעת עתה, אנחנו פשוט מקשיחים 'Day'
.
import React from "react"; import ReactDOM from "react-dom"; import ThemeContext from "./themeContext"; import App from "./App"; ReactDOM.render( , document.getElementById("root") );
צריכת הקשר עם contextType
נכון לעכשיו, ב App.js
, אנחנו פשוט מחזירים את הרכיב.
import React from "react"; import Image from "./Image"; class App extends React.Component { render() { return ( ); } } export default App;
המטרה שלנו היא להשתמש Context להחליף את classNames ב Image.js
מ Day
ל Night
, תלוי באיזה דמות שאנחנו רוצים להבהיר. לשם כך, אנו מוסיפים רכיב סטטי לרכיב שנקרא ContextType
ואז משתמשים באינטרפולציה מחרוזת כדי להוסיף אותו ל- classNames ברכיב.
כעת, classNames מכילים את המחרוזת value
מהאביזר. הערה: עברתי ThemeContext
לקובץ משלו כדי למנוע באג.
import React from "react"; import Button from "./Button"; import ThemeContext from "./themeContext"; class Image extends React.Component { render() { const theme = this.context; return ( ); } } Image.contextType = ThemeContext; export default Image;
הקשר. צרכנים
למרבה הצער, גישה זו עובדת רק עם רכיבים מבוססי כיתות. אם כבר למדת על הוקס ב- React, תדע שנוכל לעשות כמעט כל דבר עם רכיבים פונקציונליים בימינו. אז למען האמת, עלינו להמיר את הרכיבים שלנו לרכיבים פונקציונליים ואז להשתמש ThemeContext.Consumer
ברכיב כדי להעביר מידע דרך האפליקציה.
זה נעשה על ידי גלישת האלמנטים שלנו במופע של ובתוך זה (לאן
children
ללכת), מתן פונקציה המחזירה את האלמנטים. זה משתמש בתבנית "render prop" שבו אנו מספקים פונקציה קבועה כילד שמחזיר איזשהו JSX לעיבוד.
import React from "react"; import Button from "./Button"; import ThemeContext from "./themeContext"; function Image(props) { // We don't need this anymore // const theme = this.context return ( {theme => ( )} ); } // We don't need this anymore // Image.contextType = ThemeContext; export default Image;
הערה: עלינו גם לעטוף את הרכיב
- זה מאפשר לנו להוסיף פונקציונליות לכפתור בהמשך.
import React from "react"; import ThemeContext from "./themeContext"; function Button(props) { return ( {context => ( Switch ? ? )} ); } export default Button;
חלץ ספק הקשר
כרגע אנו מעבירים ערך מקודד קשה דרך הספק, אולם מטרתנו היא לעבור בין לילה ליום באמצעות הכפתור שלנו.
לשם כך נדרש להעביר את הספק שלנו לקובץ נפרד ולהכניס אותו לרכיב משלו, במקרה זה, שנקרא ThemeContextProvider
.
import React, { Component } from "react"; const { Provider, Consumer } = React.createContext(); class ThemeContextProvider extends Component { render() { return {this.props.children}; } } export { ThemeContextProvider, Consumer as ThemeContextConsumer };
הערה: מאפיין הערך מטופל כעת בקובץ החדש ThemeContext.js, ולכן יש להסירו מ- index.js.
שינוי הקשר
כדי לחבר את הכפתור, אנו מוסיפים תחילה מצב ל ThemeContextProvider
:
import React, { Component } from "react"; const { Provider, Consumer } = React.createContext(); // Note: You could also use hooks to provide state and convert this into a functional component. class ThemeContextProvider extends Component { state = { theme: "Day" }; render() { return {this.props.children}; } } export { ThemeContextProvider, Consumer as ThemeContextConsumer };
לאחר מכן, אנו מוסיפים שיטה למעבר בין יום ללילה:
toggleTheme = () => { this.setState(prevState => { return { theme: prevState.theme === "Day" ? "Night" : "Day" }; }); };
כעת אנו משנים את value
הנכס שלנו this.state.theme
כך שיחזיר את המידע מהמצב.
render() { return {this.props.children}; } }
לאחר מכן, אנו עוברים value
לאובייקט המכיל {theme: this.state.theme, toggleTheme: this.toggleTheme}
, ומעדכנים את כל המקומות בהם אנו משתמשים בערך יחיד לחיפוש theme
באובייקט. המשמעות היא שכל theme
הופך context
וכל התייחסות theme
לערך הופכת להיות context.theme
.
לבסוף, אנו אומרים לכפתור להקשיב onClick
לאירוע ואז לירות context.toggleTheme
- זה מעדכן את הצרכנים המשתמשים במדינה מהספק. הקוד של הכפתור נראה כך:
import React from "react"; import { ThemeContextConsumer } from "./themeContext"; function Button(props) { return ( {context => ( Switch ? ? )} ); } export default Button;
הכפתור שלנו מחליף כעת את התמונה בין לילה ליום בלחיצה אחת!
אזהרות הקשר
כמו כל הדברים הטובים בקוד, יש כמה אזהרות לשימוש בהקשר:
אל תשתמש בהקשר כדי להימנע מקידוח אביזרים בשכבה אחת או שתיים בלבד. ההקשר נהדר לניהול מדינה אשר דרושה חלקים גדולים של יישום. עם זאת, קידוח אביזרים מהיר יותר אם אתה רק מעביר מידע בכמה שכבות.
הימנע משימוש בהקשר כדי לשמור מצב שיש לשמור עליו באופן מקומי. אז אם אתה צריך לשמור את קלטי הטופס של המשתמש, למשל, השתמש במצב מקומי ולא בהקשר.
תמיד עוטף את הספק סביב ההורה המשותף הנמוך ביותר האפשרי בעץ - לא הרכיב ברמה הגבוהה ביותר של האפליקציה. אין צורך בעודף.
לבסוף, אם אתה מעביר אובייקט כאביזר הערך שלך, עקוב אחר הביצועים והפקטור לפי הצורך. זה כנראה לא יהיה צורך אלא אם כן ניתן יהיה להבחין בירידה בביצועים.
לעטוף
דוגמה זו היא די פשוטה וכנראה שיהיה קל יותר להכניס מדינה לאפליקציה ולהעביר אותה באמצעות אביזרים. עם זאת, אני מקווה שמראה את העוצמה שיש לצרכנים שיכולים לגשת לנתונים ללא תלות ברכיבים שמעליהם בעץ.
למידע נוסף על Context Context ותכונות נהדרות אחרות של React, תוכל להצטרף לרשימת ההמתנה לקורס React המתקדם הקרוב. או אם אתם מחפשים ידידותי למתחילים יותר, תוכלו לבדוק את קורס ההיכרות החינמי שלי בנושא React.
קידוד שמח :)