Владислав Калачев

Учим useContext на примерах — React Hooks

9 817

Доброго времени суток, друзья. Сегодня поговорим о контексте в React и работе с хуком useContext. Разберем контекст в React и какую проблему он решает. На примере передачи данных между двумя независимыми компонентами посмотрим на практическую сторону использования useContext.

Видео на эту тему.

Что такое контекст?

онтекст в React это способность передачи данных через дерево компонентов, минуя прокидывание данных через пропсы от одного компонента к другому. Если посмотреть на историю развития React, то мы увидим, что до создания Flux, Reflux, Redux и Mobx решений все данные передавались от самого верхнего компонента к нижним через пропсы, иногда минуя огромные цепочки связанных компонентов. Это было крайне неудобное решение, если приложение насчитывало сотни, а иногда даже и тысячи связанных компонентов. Чтобы решить данною проблему, разработчики React придумали Context API, благодаря которому процесс передачи стал гораздо проще и лаконичнее.

Для создания контекста достаточно воспользоваться методом React.createContext, он имеет единственный параметр, в который можно передать дефолтное значение или объект для получения дочерних компонентов через контекст.

Пример:


const context = React.createContext('value');

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

Компонент Provider

После создания контекста, его требуется использовать совместно с компонентом Provider, который позволяет дочерним компонентам подписаться на его изменения. Если проще, то благодаря компоненту Provider все дочерние компоненты могут получить значения, которые мы ему передаем.

Пример:


<Сontext.Provider value={"value"}>

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

Компонент Consumer

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

Пример:


<Context.Consumer>
   { value = > <div>value</div> }
</Context.Consumer>

Несколько контекстов

Часто одного контекста в приложении бывает не достаточно и требуется использовать несколько контекстов. Для этого как правило просто оборачивают один Provider другим и передают в них нужные значения.

Пример:


   <Context.Provider value={1}>
        <TwoContext.Provider value={2}>
          	<Page />
        </TwoContext.Provider>
     </Context.Provider>

Тоже самое делают и с Consumer для получения значений в дочерних компонентах.

Пример:


 <Context.Consumer>
      {one => (
        <TwoContext.Consumer>
          {two => (
            <Page one={one} two={two} />
          )}
        </TwoContext.Consumer>
      )}
    </Context.Consumer>

Получение контекста в Class компонентах 

Для получения контекста в Class компоненте необходимо использовать свойство contextType, имеющееся в самом классе, и присвоить объект, возвращающий контекст. После чего, используя свойства this.context, можно получить доступ к его значениям уже внутри класса.

Пример:


class ComponentOne extends React.Component {
  componentDidMount() {
    const value = this.context;
 }
  componentDidUpdate() {
    const value = this.context;
   }

  render() {
    const value = this.context;
 }
}
ComponentOne.contextType = Context;

Для чего нужен useContext?

После изучения всей базовой теории по контексту можно наконец-то перейти к хукам. Основная задача хуков в React это упрощение API с целью написания меньшего количества кода и удобства. Хук useContext занимается именно тем, что уменьшает количество написанного кода для взаимодействия с контекстом в функциональных компонентах.

Пример:


const value = useContext(Context)

Хук имеет один параметр, в который требуется передать объект контекста, получаемый при вызове React.createContext.

Важно! При изменении значений в контексте, компонент, который содержит useContext, всегда будет перерендериваться.

useContext на практике

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

Пример (App.js):


import React, { useState } from "react";
import { Context } from "./Context.js";

import ComponentA from "./ComponentA";
import ComponentB from "./ComponentB";

export default function App() {
  const [context, setContext] = useState("default context value");
  return (
    <Context.Provider value={[context, setContext]}>
      <ComponentA />
      <ComponentB />
    </Context.Provider>
  );
}

Пример (Context.js):


import React from "react";
export const Context = React.createContext();

Пример (ComponentA.js):


import React, { useContext } from "react";
import { Context } from "./Context";

export default function ComponentA() {
  const [context, setContext] = useContext(Context);
  return (
    <div>
      ComponentA:
      <button onClick={() => setContext("New Value")}>
        Change Context Value
      </button>
    </div>
  );
}

Пример (ComponentB.js):


import React, { useContext } from "react";
import { Context } from "./Context";

export default function ComponentB() {
  const [context, setContext] = useContext(Context);
  return <div>ComponentB: {context}</div>;
}

Давайте разберем по шагам, что происходит в этом примере. В Context.js создается сам контекст, а в App.js импортируются два компонента и контекст, которым они оборачиваются, c передачей в value начального состояния (context) и функции для его изменения (setContext).

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

При нажатии на кнопку в компоненте ComponentA происходит изменение значения контекста, благодаря useContext в компоненте ComponentB происходит его моментальное перерендеривание и, как результат в нем отображается значение контекста.

Заключение

Сегодня мы разобрали понятие контекста в React и на примерах посмотрели практическое применение useContext. Благодаря использованию useContext работа с контекстом стала более лаконичной и простой. Помните, использование контекста в вашем приложении может усложнить повторное использование компонентов, и в качестве альтернативы вы можете использовать более простое и эффективное решение, а именно композицию компонентов. Надеюсь, что данная статья была вам полезна. Учитесь, думайте, пишите код. Удачного кодинга, друзья!

Подписывайтесь на наш канал в Telegram и на YouTube для получения самой последней и актуальной информации. 

Комментарии:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *