useContext hook
Props дамжуулах нь нэг, хоёр түвшинд тохиромжтой. Гэвч апп томрох тусам App → Layout → Sidebar → UserMenu → Avatar гэх мэт олон давхаргаар нэг зүйлийг дамжуулах шаардлага гардаг. Энийг prop drilling гэнэ — утгыг зөвхөн дамжуулахын тулд дунд компонентуудаар "өрөмдөж" ордог учраас. useContext hook энэ асуудлыг шийддэг — өгөгдлийг шууд хэрэгтэй component-д хүргэдэг.
Context үүсгэх
Context ашиглахад гурван алхам байдаг: үүсгэх, Provider-ээр боох, унших:
// context/ThemeContext.jsx
import { createContext } from "react";
// 1. Context үүсгэнэ — default утга өгч болно
const ThemeContext = createContext("dark");
export default ThemeContext;
// App.jsx
import { useState } from "react";
import ThemeContext from "./context/ThemeContext";
import Page from "./components/Page";
function App() {
const [theme, setTheme] = useState("dark");
// 2. Provider-ээр хүүхэд component-уудыг боодог
return (
<ThemeContext.Provider value={theme}>
<button
onClick={() => setTheme((t) => (t === "dark" ? "light" : "dark"))}
>
Загвар солих
</button>
<Page />
</ThemeContext.Provider>
);
}
// components/Avatar.jsx — хэд хэдэн түвшний доор байгаа ч шууд авна
import { useContext } from "react";
import ThemeContext from "../context/ThemeContext";
function Avatar() {
// 3. useContext ашиглан унших
const theme = useContext(ThemeContext);
return (
<div style={{ background: theme === "dark" ? "#0f172a" : "#f1f5f9" }}>
Профайл
</div>
);
}
Provider-н value-д дамжуулсан утга нь доорх бүх component-д ямар ч props дамжуулалтгүйгээр хүрнэ.
Хэрэглэгчийн мэдээлэл дамжуулах
Нэвтэрсэн хэрэглэгчийн мэдээллийг апп даяар хуваалцах хамгийн нийтлэг хэрэглээ:
// context/UserContext.jsx
import { createContext, useContext, useState } from "react";
const UserContext = createContext(null);
// Provider component — логикийг хамт хадгална
export function UserProvider({ children }) {
const [user, setUser] = useState(null);
function login(userData) {
setUser(userData);
}
function logout() {
setUser(null);
}
return (
<UserContext.Provider value={{ user, login, logout }}>
{children}
</UserContext.Provider>
);
}
// Custom hook — хялбар унших
export function useUser() {
return useContext(UserContext);
}
// App.jsx
import { UserProvider } from "./context/UserContext";
function App() {
return (
<UserProvider>
<Navbar />
<Main />
</UserProvider>
);
}
// components/Navbar.jsx
import { useUser } from "../context/UserContext";
function Navbar() {
const { user, logout } = useUser();
return (
<nav>
{user ? (
<>
<span>{user.username}</span>
<button onClick={logout}>Гарах</button>
</>
) : (
<a href="/login">Нэвтрэх</a>
)}
</nav>
);
}
Олон Context хослуулах
Нэг аппад хэд хэдэн context хамт ажиллаж болно:
// App.jsx
import { ThemeProvider } from "./context/ThemeContext";
import { UserProvider } from "./context/UserContext";
import { LanguageProvider } from "./context/LanguageContext";
function App() {
return (
<UserProvider>
<ThemeProvider>
<LanguageProvider>
<Router />
</LanguageProvider>
</ThemeProvider>
</UserProvider>
);
}
// Дурын component дотор хэдэн context-аас ч унших боломжтой
function SettingsPage() {
const { user } = useUser();
const { theme, setTheme } = useTheme();
const { language, setLanguage } = useLanguage();
return (
<div>
<h2>{user.username}-н тохиргоо</h2>
<select value={theme} onChange={(e) => setTheme(e.target.value)}>
<option value="dark">Харанхуй</option>
<option value="light">Цайвар</option>
</select>
</div>
);
}
Context хэзээ ашиглах вэ?
Context бол хүчирхэг боловч хэрэв буруу ашиглавал апп удааширдаг — Provider-н value өөрчлөгдөх бүрт дотор бүх component дахин рендер болдог:
// ❌ Буруу — объект literal шууд value-д байвал рендер болгонд шинэ объект үүснэ
<UserContext.Provider value={{ user, login, logout }}>
// ✅ Зөв — useMemo ашиглан object-г тогтворжуулна
import { useMemo } from 'react'
function UserProvider({ children }) {
const [user, setUser] = useState(null)
const value = useMemo(() => ({
user,
login: (data) => setUser(data),
logout: () => setUser(null),
}), [user])
return (
<UserContext.Provider value={value}>
{children}
</UserContext.Provider>
)
}
Context-г ашиглах нь зөв тохиолдол: theme, хэрэглэгчийн мэдээлэл, хэлний тохиргоо, глобал modal/toast. Хэрэв өгөгдөл хоёр, гурав л түвшин дамжих бол энгийн props хангалттай.
Дараагийн хичээлд:
useReducer hook ашиглан нарийн төвөгтэй state логикийг зохион байгуулах аргыг судална. useState-с хэзээ шилжих, reducer функц бичих аргыг жишээгээр ойлгоно.