React useContext

Контекст в React

Контекст (Context) в React — это способ управления глобальным состоянием в приложении.

Его можно использовать совместно с хуком useState, чтобы легко делиться состоянием между глубоко вложенными компонентами, чего трудно добиться только с помощью useState.


Проблема

Состояние должно находиться в самом высоком родительском компоненте, которому необходимо получить доступ к этому состоянию.

Для иллюстрации предположим, что у нас есть многоуровневая иерархия компонентов, где верхний и нижний компоненты нуждаются в доступе к состоянию.

Без использования Context нам придётся передавать состояние через промежуточные компоненты в виде "пропсов". Это называется пробиванием пропсов (prop-drilling).

Пример

Передача "пропсов" через вложенные компоненты:


import { useState } from 'react';
import { createRoot } from 'react-dom/client';

function Component1() {
  const [user, setUser] = useState("Linus");

  return (
    <>
      <h1>{`Привет, ${user}!`}</h1>
      <Component2 user={user} />
    </>
  );
}

function Component2({ user }) {
  return (
    <>
      <h1>Component 2</h1>
      <Component3 user={user} />
    </>
  );
}

function Component3({ user }) {
  return (
    <>
      <h1>Component 3</h1>
      <h2>{`И снова привет, ${user}!`}</h2>
    </>
  );
}

createRoot(document.getElementById('root')).render(
  <Component1 />
);

Даже если компонент 2 не нуждался в состоянии, он вынужден передавать его дальше, чтобы обеспечить доступ к состоянию компоненту 3.


Решение

Решение состоит в создании контекста.

Создание контекста

Чтобы создать контекст, нужно импортировать createContext и инициализировать его:


import { useState, createContext, useContext } from 'react';
import { createRoot } from 'react-dom/client';

const UserContext = createContext();

Далее мы используем провайдер контекста для обертывания деревьев компонентов, нуждающихся в доступе к состоянию контекста.

Провайдер контекста

Оберните дочерние компоненты в провайдер контекста UserConter.Provider и предоставьте им значение состояния.


function Component1() {
  const [user, setUser] = useState("Linus");

  return (
    <UserContext.Provider value={user}>
      <h1>{`Привет, ${user}!`}</h1>
      <Component2 />
    </UserContext.Provider>
  );
}

Теперь все компоненты в дереве получат доступ к контексту пользователя.

Использование хука useContext

Чтобы использовать контекст в дочернем компоненте, нужно обратиться к нему с помощью хука useContext.

Сначала добавьте useContext в оператор импорта:


import { useState, createContext, useContext } from "react";

Тогда вы сможете получить доступ к контексту пользователя во всех компонентах:


function Component3() {
  const user = useContext(UserContext);

  return (
    <>
      <h1>Component 3</h1>
      <h2>{`И снова привет, ${user}!`}</h2>
    </>
  );
}


Полный пример

Полный пример использования React Context:

Пример


import { useState, createContext, useContext } from 'react';
import { createRoot } from 'react-dom/client';

const UserContext = createContext();

function Component1() {
  const [user, setUser] = useState("Linus");

  return (
    <UserContext.Provider value={user}>
      <h1>{`Привет, ${user}!`}</h1>
      <Component2 />
    </UserContext.Provider>
  );
}

function Component2() {
  return (
    <>
      <h1>Component 2</h1>
      <Component3 />
    </>
  );
}

function Component3() {
  const user = useContext(UserContext);

  return (
    <>
      <h1>Component 3</h1>
      <h2>{`И снова привет, ${user}!`}</h2>
    </>
  );
}

createRoot(document.getElementById('root')).render(
  <Component1 />
);