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ҳамаи хонандагонро аз нав мекашад. Барои маълумоти зуд-зуд тағйирёбанда (мавқеи муш, матн дар майдон) контекст интихоби бад аст.
Номзадҳои хуб барои контекст: корбари ҷорӣ, мавзӯъ, забон, сабад, танзимот.
Хатоҳои маъмул
- Компонент берун аз Provider.
useContextхомӯшона қимати пешфарзро (null) бармегардонад, ва дар ягон ҷои минбаъдаCannot read properties of nullмешавад. Хук бо санҷиш фавран хатои фаҳмо медиҳад. - Ба
useContextдодани объекти нодуруст.useContext(ThemeContext)лозим аст, наuseContext(ThemeContext.Provider)ё сатр. value-ро фаромӯш кардан.<Ctx.Provider>беvalueundefined-ро медиҳад.- Интизор шудан, ки тағйири объект дар дохили
valueэкранро нав мекунад. Мисли ҳолат: объекти нав тавассутиset…лозим аст.
Хулоса
- Контекст маълумотро ба чуқурии дарахт бе props медиҳад:
createContext→<Ctx.Provider value>→useContext(Ctx). useContextқимати Provider-и наздиктаринро болотар мегирад, вагарна — қимати пешфарз.- Ҳангоми тағйири
valueҳамаи хонандагони контекст аз нав кашида мешаванд. - Контекст +
useStateдар компоненти провайдер = ҳолати умумии тағйирёбандаи барнома. - Хуки худи
useX()бо санҷиш баnull— қулай ва бехатар. - Барои маълумот ба 1–2 сатҳ — props-и оддӣ.