Глобальное состояние в React без подключения сторонних библиотек
Когда в проекте React (Next.js) требуется внедрить глобальное состояние, которое должно быть доступно в различных компонентах не только для чтения, но и для изменения, то на ум приходят такие библиотеки, как Redux, Zustand, Jotai и т.п. Каждая из этих библиотек имеет свои преимущества и недостатки, но в этой статье речь пойдет немного о другом.
В подавляющем большинстве проектов для внедрения глобального состояния можно обойтись стандартным функционалом React, а подключение сторонней библиотеки является неоправданным и избыточным.
Решение
1. Создаём провайдер глобального состояния ExampleProvider, которое должно быть доступно для чтения example и изменения setExample() в любом месте проекта:
"use client";
import { createContext, useContext, useState } from "react";
const ExampleContext = createContext(0);
const ExampleSetContext = createContext(null);
export default function ExampleProvider({ children }) {
const [example, setExample] = useState(0);
return (
<ExampleContext value={example}>
<ExampleSetContext value={setExample}>{children}</ExampleSetContext>
</ExampleContext>
);
}
export function useExample() {
return {
example: useContext(ExampleContext),
setExample: useContext(ExampleSetContext),
};
}В этом примере глобальное состояние example является числовым, но может быть любого типа, включая сложные объекты.
2. Подключаем провайдер глобального состояния в корневом макете:
import "./globals.css";
import ExampleProvider from "@/lib/example";
export default function RootLayout({ children }) {
return (
<html lang="ru">
<body>
<ExampleProvider>{children}</ExampleProvider>
</body>
</html>
);
}Теперь глобальное состояние example и функция его изменения setExample() будут доступны в любом месте проекта.
3. Пример использования глобального состояния example в компоненте:
"use client";
import { useExample } from "@/lib/example";
export default function Component() {
const { exapmle, setExample } = useExample();
return (
<button onClick={() => setExample((n) => n + 1)}>Example: {example}</button>
);
}В этом компоненте импортируются как само глобальное состояние exapmle, так и функция его изменения setExample(). Но это решение позволяет в одних компонентах импортировать только значение глобального состояния exapmle, а в других только функцию его изменения setExample().






