JS: React
2026-02-26 22:56 Diff

Передача данных через пропсы вниз по иерархии компонентов — это немного многословный, но простой механизм. Всегда видно, откуда пришли данные и как они попали внутрь, а компоненты легко переиспользовать, так как они зависят только от входных данных. Но бывают ситуации, когда передача пропсов не вписывается в то, как работает код.

Возьмем для примера текущего пользователя. Часто данные пользователя нужны одновременно в разных частях страницы, причем в очень глубоких компонентах. Для этого придется передавать пользователя буквально по всей иерархии: даже там, где он не нужен компоненту. Единственная цель такой передачи — прокинуть данные до места назначения, пройдя по пути все промежуточные компоненты. Получается, что множество компонентов никак не используют пользователя, они просто передают их дальше по цепочке. В нашей ситуации данные пользователя глобальные. Они нужны сразу многим компонентам на разных уровнях иерархии. Для таких задач в React существует обходной путь.

Context API — механизм, позволяющий сделать глобальные данные доступными из любого компонента напрямую, без прокидывания пропсов. Его использование сводится к трем шагам:

  1. Создание контекста:

  2. Передача данных в контекст. Работает так: оборачиваем нужные компоненты в компонент контекста <UserContext.Provider> и передаем туда нужные данные в проп value:

  3. Получение данных из контекста. В компоненте, где нужны данные, нужно указать тип контекста с помощью статического свойства contextType. Реакт ищет ближайший провайдер этого контекста и берет из него значение. Поиск провайдера происходит вверх по дереву компонентов. Значение контекста будет доступно в this.context:

Попрактиковаться

Еще один пример, где несколько компонентов используют данные из контекста:

Попрактиковаться

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

Рассмотрим пример, когда контекст используется совместно с изменяемыми данными. Для этого расширим наш пример, добавив больше компаний и переключение между ними:

Разберем пример:

  1. Мы создали контекст CompanyContext, который хранит информацию о нескольких компаниях, текущую выбранную компанию и функцию для изменения компании.
  2. В компоненте <App/> определено состояние с текущей компанией и метод для её изменения.
  3. Компоненты <CompanyNameComponent/> и <CompanyAddressComponent/> получают данные из контекста и отображают название и адрес текущей компании.
  4. <CompanySwitcher/> позволяет переключать между компаниями, обновляя состояние и тем самым меняя отображаемые данные на странице.

При изменении данных в контексте компоненты, которые зависят от этих данных, будут перерисованы. Это происходит благодаря тому, что состояние, хранящее данные контекста, изменяется в компоненте-родителе (<App/>), и новое значение контекста передается вниз через провайдер. Это удобно для таких задач, где изменение состояния напрямую влияет на всё приложение (например переключение темы, языка, пользователя и тд).

Попрактиковаться