Глобальное состояние в React без подключения сторонних библиотек

14 января 2026 г.

Когда в проекте React (Next.js) требуется внедрить глобальное состояние, которое должно быть доступно в различных компонентах не только для чтения, но и для изменения, то на ум приходят такие библиотеки, как Redux, Zustand, Jotai и т.п. Каждая из этих библиотек имеет свои преимущества и недостатки, но в этой статье речь пойдет немного о другом.

В подавляющем большинстве проектов для внедрения глобального состояния можно обойтись стандартным функционалом React, а подключение сторонней библиотеки является неоправданным и избыточным.

Решение

1. Создаём провайдер глобального состояния ExampleProvider, которое должно быть доступно для чтения example и изменения setExample() в любом месте проекта:

/lib/example.js
"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. Подключаем провайдер глобального состояния в корневом макете:

/app/layout.js
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 в компоненте:

/ui/component.js
"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().