Для каких целей используешь React Context
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
React Context: Назначение и применение
React Context — это механизм для передачи данных между компонентами без необходимости передавать props через каждый промежуточный компонент (避免prop drilling). Это встроенное в React решение для управления глобальным состоянием на уровне приложения или его части.
Основные цели использования Context
1. Избежание Prop Drilling Когда данные нужны глубокому компоненту, но передаются через несколько промежуточных уровней, код становится сложным для поддержки:
// Плохо — prop drilling
<App user={user}>
<Header user={user}>
<Nav user={user}>
<UserMenu user={user} />
</Nav>
</Header>
</App>
С Context это становится проще:
const UserContext = React.createContext();
<UserContext.Provider value={user}>
<App />
</UserContext.Provider>
// Внутри UserMenu
const user = useContext(UserContext);
2. Глобальное состояние (Theme, Auth, Locale) Context идеален для данных, которые нужны многим компонентам по всему приложению:
- Тема оформления (Light/Dark mode) — один раз установили, все компоненты её используют
- Данные авторизации — информация о текущем пользователе
- Язык интерфейса (i18n) — текущая локализация
- Глобальные настройки — часовой пояс, формат дат
interface AuthContextType {
user: User | null;
isLoading: boolean;
login: (credentials: Credentials) => Promise<void>;
logout: () => void;
}
const AuthContext = React.createContext<AuthContextType | undefined>(undefined);
export function AuthProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<User | null>(null);
const [isLoading, setIsLoading] = useState(false);
const login = async (credentials: Credentials) => {
setIsLoading(true);
try {
const response = await fetch("/api/login", {
method: "POST",
body: JSON.stringify(credentials),
});
const data = await response.json();
setUser(data.user);
} finally {
setIsLoading(false);
}
};
const logout = () => setUser(null);
return (
<AuthContext.Provider value={{ user, isLoading, login, logout }}>
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
const context = useContext(AuthContext);
if (!context) throw new Error("useAuth must be used within AuthProvider");
return context;
}
3. Временное UI-состояние Для состояния, которое влияет на несколько компонентов, но не требует сложной логики:
- Открыт ли модальное окно
- Активная вкладка
- Фильтры в списке
4. Комбинирование нескольких Contexts Для сложных приложений часто нужно несколько contexts:
<AuthProvider>
<ThemeProvider>
<LocalizationProvider>
<App />
</LocalizationProvider>
</ThemeProvider>
</AuthProvider>
Когда НЕ использовать Context
- Часто меняющиеся данные — Context вызывает ре-рендеринг всех подписчиков. Для частых изменений лучше использовать Zustand, Redux или другую библиотеку состояния
- Сложная бизнес-логика — Context не предназначен для управления сложным состоянием
- Данные нескольких пользователей — Context хранит данные в памяти, для больших объёмов это неэффективно
Пример: Theme Provider
type Theme = "light" | "dark";
interface ThemeContextType {
theme: Theme;
toggleTheme: () => void;
}
const ThemeContext = React.createContext<ThemeContextType | undefined>(undefined);
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState<Theme>(() => {
const saved = localStorage.getItem("theme") as Theme | null;
return saved || "light";
});
const toggleTheme = () => {
setTheme((prev) => (prev === "light" ? "dark" : "light"));
localStorage.setItem("theme", theme === "light" ? "dark" : "light");
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
const context = useContext(ThemeContext);
if (!context) throw new Error("useTheme must be used within ThemeProvider");
return context;
}
Производительность и оптимизация
Когда Context часто обновляется, это может вызвать лишние ре-рендеринги. Решение — разделить Context на несколько, или использовать useMemo:
const value = useMemo(() => ({ user, isLoading, login, logout }), [user, isLoading, login, logout]);
<AuthContext.Provider value={value}>
{children}
</AuthContext.Provider>
Итоговый вывод: React Context — это лучший выбор для управления глобальным состоянием небольшого объёма (auth, theme, settings), которое меняется не очень часто. Для более сложных сценариев стоит рассмотреть Zustand или Redux.