Гузариш ба мундариҷа
Мавзӯи 8 аз 13
Назария

useContext: маълумот барои тамоми барнома

Мушкил: props тавассути даҳ сатҳ

Маълумот дар React аз боло ба поён тавассути props ҷорӣ мешавад. Одатан ин хуб аст: намоён аст, ки чӣ аз куҷо омад. Аммо баъзе маълумот ба қариб ҳамаи компонентҳо лозим аст: корбари ҷорӣ, мавзӯи ороиш, забон, сабад. Онҳоро тавассути props аз ҳар компоненти мобайнӣ гузарондан лозим меояд — ҳатто аз онҳое, ки ба онҳо лозим нестанд:

function App() {
  const [user, setUser] = useState({ name: "Аня" });
  return <Layout user={user} />;
}
function Layout({ user }) {
  return <Header user={user} />;        // Layout худаш user-ро истифода намебарад
}
function Header({ user }) {
  return <Menu user={user} />;          // Header ҳам
}
function Menu({ user }) {
  return <p>Салом, {user.name}</p>;     // танҳо ин ҷо лозим аст
}

Инро prop drilling («пармакунии» props) меноманд. Код нозук мешавад: барои илова кардани қимати нав ҳамаи компонентҳои мобайниро иваз кардан лозим аст.

Контекст ба компоненти боло имкон медиҳад, ки қиматро «эълон кунад», ва ба ҳар компоненти поёнтар — онро мустақим хонад, бе гузарондан тавассути сатҳҳои мобайнӣ.

Се қадам: сохтан, додан, хондан

const { createContext, useContext } = React;

// 1. Контекстро сохтан (одатан дар файли алоҳида). Аргумент — қимати пешфарз
const UserContext = createContext(null);

// 2. Қиматро додан: қисми дарахтро ба Provider печондан
function App() {
  const [user, setUser] = useState({ name: "Аня" });
  return (
    <UserContext.Provider value={user}>
      <Layout />
    </UserContext.Provider>
  );
}

function Layout() {
  return <Header />;          // ҳеҷ props
}
function Header() {
  return <Menu />;
}

// 3. Дар ҳар компоненти дохили Provider хондан
function Menu() {
  const user = useContext(UserContext);
  return <p>Салом, {user.name}</p>;
}
  • createContext(қиматиПешфарз) объекти контекстро месозад.
  • <Ctx.Provider value={...}> қиматро ба ҳамаи компонентҳои дохил, дар ҳар чуқурӣ дастрас мекунад.
  • useContext(Ctx) қимати Provider-и наздиктарин-ро болотар дар дарахт бармегардонад. Агар Provider набошад — қимати пешфарз.

Вақте қимат тағйир меёбад

Вақте value-и Provider тағйир меёбад, React ҳамаи компонентҳоеро, ки ин контекстро тавассути useContext мехонанд, аз нав мекашад — ҳатто агар волидонашон аз нав кашида нашуда бошанд. Ҳамин тавр контекст дар тамоми барнома актуалӣ мемонад.

Provider-ҳоро ба ҳам ҷойгир кардан мумкин аст: дарунӣ барои қисми дарахти худ берунаро «мепӯшонад».

<ThemeContext.Provider value="dark">
  <Page />                          {/* ин ҷо мавзӯъ dark */}
  <ThemeContext.Provider value="light">
    <Footer />                      {/* ин ҷо бошад light */}
  </ThemeContext.Provider>
</ThemeContext.Provider>

Контекст + ҳолат

Худи контекст чизеро нигоҳ намедорад — вай танҳо қиматро ба поён медиҳад. Барои он ки маълумотро иваз кардан мумкин бошад, контекстро бо ҳолат пайваст мекунанд ва ба поён ҳам қимат ва ҳам функсияҳои ивазкуниро медиҳанд:

const AuthContext = createContext(null);

function AuthProvider({ children }) {
  const [user, setUser] = useState(null);

  const login = (name) => setUser({ name });
  const logout = () => setUser(null);

  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
}

function LoginButton() {
  const { user, login, logout } = useContext(AuthContext);
  return user
    ? <button onClick={logout}>Баромадан ({user.name})</button>
    : <button onClick={() => login("Аня")}>Ворид шудан</button>;
}

function App() {
  return (
    <AuthProvider>
      <Header />
      <LoginButton />
    </AuthProvider>
  );
}

Ин нақшаи стандартӣ аст: компонент-«провайдер» бо ҳолат дар дохил ва children дар берун. Тавассути children тамоми барнома дар дохили Provider мемонад.

Хуки худ барои контекст

Дар лоиҳаҳо қариб ҳамеша хуки хурди печонак месозанд. Вай кӯтоҳтар аст ва фавран дар бораи хато хабар медиҳад, агар компонент тасодуфан берун аз провайдер монда бошад:

function useAuth() {
  const value = useContext(AuthContext);
  if (value === null) {
    throw new Error("useAuth must be used inside AuthProvider");
  }
  return value;
}

function Profile() {
  const { user } = useAuth();      // ба ҷойи useContext(AuthContext)
  return <p>{user ? user.name : "Меҳмон"}</p>;
}

Хук — функсияи оддӣ аст, ки номаш бо use сар мешавад ва дар дохили он хукҳои дигар даъват мешаванд. Муфассалтар дар бораи хукҳои худ — дар мавзӯъ дар бораи бор кардани маълумот.

Кай контекст лозим нест

Контекст қулай аст, вале ба он ҳама чизро гузоштан лозим нест:

  • агар маълумот ба як-ду сатҳ поёнтар лозим бошад — props диҳед, ин соддатар ва равшантар аст;
  • аксар вақт композитсия кӯмак мекунад: ба ҷойи гузарондани маълумот тавассути Layout унсури тайёрро тавассути children диҳед — <Layout><Menu user={user} /></Layout>;
  • ҳар тағйири value ҳамаи хонандагонро аз нав мекашад. Барои маълумоти зуд-зуд тағйирёбанда (мавқеи муш, матн дар майдон) контекст интихоби бад аст.

Номзадҳои хуб барои контекст: корбари ҷорӣ, мавзӯъ, забон, сабад, танзимот.

Хатоҳои маъмул

  1. Компонент берун аз Provider. useContext хомӯшона қимати пешфарзро (null) бармегардонад, ва дар ягон ҷои минбаъда Cannot read properties of null мешавад. Хук бо санҷиш фавран хатои фаҳмо медиҳад.
  2. Ба useContext додани объекти нодуруст. useContext(ThemeContext) лозим аст, на useContext(ThemeContext.Provider) ё сатр.
  3. value-ро фаромӯш кардан. <Ctx.Provider> бе value undefined-ро медиҳад.
  4. Интизор шудан, ки тағйири объект дар дохили value экранро нав мекунад. Мисли ҳолат: объекти нав тавассути set… лозим аст.

Хулоса

  • Контекст маълумотро ба чуқурии дарахт бе props медиҳад: createContext → <Ctx.Provider value> → useContext(Ctx).
  • useContext қимати Provider-и наздиктаринро болотар мегирад, вагарна — қимати пешфарз.
  • Ҳангоми тағйири value ҳамаи хонандагони контекст аз нав кашида мешаванд.
  • Контекст + useState дар компоненти провайдер = ҳолати умумии тағйирёбандаи барнома.
  • Хуки худи useX() бо санҷиш ба null — қулай ва бехатар.
  • Барои маълумот ба 1–2 сатҳ — props-и оддӣ.

Тугма бо ранги мавзӯъ

Осон+10 XP

Контексти ThemeContext аллакай сохта шудааст (пешфарз "light"). Компоненти ThemeButton-ро бо children нависед: вай <button>-ро бо ҳамин матн мекашад, ва синфи тугма (className)-ро аз контекст мегирад.

<ThemeContext.Provider value="dark">
  <ThemeButton>OK</ThemeButton>       → <button class="dark">OK</button>
</ThemeContext.Provider>
<ThemeButton>OK</ThemeButton>         → <button class="light">OK</button>   (бе Provider)

Барои ҳал кардани масъалаҳо коннекторро пайваст кун

Коди масъалаҳо дар компютери худат иҷро мешавад — ин аз браузер тезтар ва боэътимодтар аст. Барои ин барномаи ройгони коннектори CodeWithMe лозим аст. Онро як бор пайваст кардан кифоя аст.

Коннекторро дар ин компютер ҷустуҷӯ мекунем…

  1. 1
    Коннекторро барои системаи худ (Windows, macOS ё Linux) зеркашӣ кун.Зеркашии коннекторДар саҳифаи зеркашӣ файлеро интихоб кун, ки дар номаш системаи ту ҳаст, масалан windows-amd64.
  2. 2Онро иҷро кун ва ҷузвдонеро интихоб кун, ки ҳалҳоят дар он ҷо меистанд. Python ва Node.js-ро ӯ худаш ҳангоми зарурат ба он ҷо мегузорад.
  3. 3
    Дар поён рамзи 6-рақамаро ворид кун — он дар равзанаи коннектор навишта шудааст («Рамз барои сайти CodeWithMe»). Агар браузер дар бораи дастрасӣ ба шабакаи маҳаллӣ пурсад — иҷозат деҳ.

Коннектор кушода аст (рамзи манбаъ дар GitHub), танҳо дар компютери ту кор мекунад ва кодро танҳо пас аз ворид кардани рамзи пайвастшавӣ иҷро мекунад.