Translate

Поиск по этому блогу

четверг, 28 мая 2020 г.

React. Как использовать «useContext» в React Hooks

Следующая статья посвящена пониманию работы хуков «useContext» в компонентах React.



Хук «useContext» используется для создания общих данных, к которым можно обращаться по всей иерархии компонентов, не пропуская реквизиты - props вручную до каждого уровня. Определенный контекст будет доступен для всех дочерних компонентов без использования props.

Ниже приводится цитата о контексте с официальной веб-страницы React:

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

В типичном React-приложении данные передаются сверху вниз (от родителя к дочернему компоненту) с помощью пропсов. Однако, этот способ может быть чересчур громоздким для некоторых типов пропсов (например, выбранный язык, UI-тема), которые необходимо передавать во многие компоненты в приложении. Контекст предоставляет способ делиться такими данными между компонентами без необходимости явно передавать пропсы через каждый уровень дерева.


В статье ниже мы сосредоточимся на том, как «useContext» работает программно. Но прежде чем начать с «useContext», давайте сначала разберемся, как сделать данные доступными от родительских к дочерним компонентам, используя атрибуты «props». Затем мы введем хук «useContext» для компонента, чтобы понять его влияние.

Передача данных в дочерние компоненты без «useContext»

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

import React, { useState } from "react";

function UserDetailsComponent() {
  var [userDetails, setUserDetails] = useState({
    name: "Yaroslav",
    age: 50
  });
                                               
  return (
    <div>
      <h1>This is the Parent Component</h1>
    </div>                                         
  )
}


Теперь давайте введем еще два компонента в иерархию, мы добавим к иерархии «ChildComponent», который по-прежнему не будет получать доступ к данным, доступным из родительского компонента. ChildComponent должен далее передать эти данные своему дочернему компоненту «SubChildComponent», где данные, наконец, отображаются.

Расширяя код далее, мы отправим переменную состояния далее в дочерний компонент «ChildComponent» с помощью «props», который отправит эти данные дальше в его дочерний компонент «SubChildComponent». Давайте посмотрим на код ниже, чтобы объяснить дальнейшие сценарии.

import React, { useState } from "react";

function UserDetailsComponent() {
  var [userDetails, setUserDetails] = useState({
    name: "Yaroslav",
    age: 50,
  });

  return (
    <div>
      <h1>This is the Parent Component</h1>
      <hr />
      <ChildComponent userDetails={userDetails}></ChildComponent>
    </div>
  );
}

function ChildComponent(props) {
  return (
    <div>
      <h2>This is Child Component</h2>
      <hr />
      <SubChildComponent userDetails={props.userDetails}></SubChildComponent>
    </div>
  );
}

function SubChildComponent(props) {
  return (
    <div>
      <h3>This is Sub Child Component</h3>
      <h4>User Name: {props.userDetails.name}</h4>
      <h4>User Age: {props.userDetails.age}</h4>
    </div>
  );
}



В приведенном выше коде родительский компонент определяет некоторые переменные состояния, которые не используются внутри компонента, вместо этого он отправляется далее дочернему компоненту «ChildComponent» в качестве данных «props». «ChildComponent» не использует «userDetails» и далее отправляет данные своему дочернему компоненту «SubChildComponent» в качестве «propsх» данных. Этот «SubChildComponent» использует данные, переданные ему как «props», и отображает имя пользователя и возраст в компоненте.

Вы можете поиграть с вышеуказанным кодом в следующем онлайн-редакторе: Code Sandbox link

Проблема с вышеуказанным кодом

Я бы попытался объяснить проблему с приведенным выше кодом, указав приведенные ниже утверждения. Надеюсь, это будет иметь смысл для вас.
  1. Данные состояния определяются на верхнем уровне, определенные данные передаются дочернему компоненту, где данные больше не используются. Данные от родителя передаются как «props» данные. Эти «props» данные не влияют на дочерний компонент, но, тем не менее, дочерний компонент должен поддерживать данные «props».
  2. «ChildComponent» далее передает эти «props» данные «SubChildComponent». «ChildComponent» здесь просто идут издержки на управление «props» из родительского компонента, только для того, чтобы сделать его доступным для других дочерних компонентов.
  3. Нам необходимо явно передавать «props» даже тем компонентам, которые даже не используют его только для того, чтобы сделать данные доступными для иерархии ниже. Мы поддерживаем постоянную передачу данных «props» по всей иерархии приложения.
Я надеюсь, что вы сможете решить проблему с передачей «props» по всей иерархии приложения. 😉

«UseContext» для спасения…

Чтобы решить вышеупомянутую проблему передачи «props» данных даже тем компонентам, которые не требуют этого только потому, что данные требуются в дальнейшей иерархии, мы можем использовать «Context API».

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

Давайте воссоздадим приведенный выше пример с «Context API» и увидим разницу.

Чтобы достичь этого, мы сначала создадим объект контекста. После того, как объект создан с использованием React.createContext. Затем мы будем использовать этот объект контекста в компоненте верхнего уровня и добавим данные, необходимые для всей иерархии. UserDetailContext.Provider используется для предоставления значения созданному объекту контекста. Объект, который необходимо добавить, предоставляется атрибуту value.

import React, { useState } from "react";

var userDetailContext = React.createContext(null);

export default function UserDetailsComponent() {
  var [userDetails] = useState({
    name: "Mayank",
    age: 30
  });

  return (
    <userDetailContext.Provider value={userDetails}>
      <h1>This is the Parent Component</h1>
      <hr />
      <ChildComponent userDetails={userDetails} />
    </userDetailContext.Provider>
  );
}


В приведенном выше коде мы создали объект контекста userDetailsContext и добавляем данные о состоянии в контекст в UserDetailsComponent. Поскольку данные добавляются в контекст, предоставленный в этом компоненте, любой компонент в иерархии будет иметь доступ к данным контекста.

Далее, мы хотим, чтобы данные получали доступ через SubChildComponent, не передавая их как «props» данные. Чтобы получить доступ к данным в SubChildComponent, нам нужно получить доступ к контексту, созданному ранее на верхнем уровне, и получить доступ к данным, доступным в этом контексте.

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

React.useContext(userDetailContext);

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

import React, { useState } from "react";

var userDetailContext = React.createContext(null);

export default function UserDetailsComponent() {
  var [userDetails] = useState({
    name: "Yaroslav",
    age: 50,
  });

  return (
    <userDetailContext.Provider value={userDetails}>
      <h1>This is the Parent Component</h1>
      <hr />
      <ChildComponent userDetails={userDetails} />
    </userDetailContext.Provider>
  );
}

function ChildComponent(props) {
  return (
    <div>
      <h2>This is Child Component</h2>
      <hr />
      <SubChildComponent />
    </div>
  );
}

function SubChildComponent(props) {
  var contextData = React.useContext(userDetailContext);
  return (
    <div>
      <h3>This is Sub Child Component</h3>
      <h4>User Name: {contextData.name}</h4>
      <h4>User Age: {contextData.age}</h4>
    </div>
  );
}



В приведенном выше примере мы видим, что ключевое слово useContext сделает данные родительского компонента доступными для дочерних компонентов на любом уровне в иерархии, не раскрывая их как «props» данные. Вы можете играть с кодом в следующем онлайн-редакторе ... Code Sandbox link

Использование

Считается, что связка двух хуков - useContext + useReducer(о нем я расскажу в следующий раз) может полностью заменить Redux! Мнения "за":
  • Вы можете использовать хуки (useContext + useReducer) вместо Redux в не больших приложениях (где нет необходимости в больших комбинированных Reducers). В данном случае Redux действительно может оказаться избыточным.
Мнения "против":
  • Большое количество кода уже написано на связке React + Redux и переписывать его на хуки (useContext + useReducer) кажется мне не целесообразным, по крайней мере сейчас.
  • Redux — проверенная библиотека, хуки — нововведение, их интерфейсы и поведение может измениться в дальнейшем.
  • Для того чтобы сделать использование useContext + useReducer действительно удобным, придется написать некоторые велосипеды.
Выводы делайте сами, а мой ниже...😉

Вывод

«UseContext» - это удивительный способ избавиться от издержек, связанных с передачей данных через props на разные уровни иерархии, даже если это не требуется.

Попробуйте поработать с React Hooks некоторое время и эти интересные функции, которые заставят вас задуматься о функциональном программировании.

Хотите оставаться в курсе новинок в области JS-программирования? Подписывайтесь на мой канал, вступайте в группу на Facebook. Если понравившаяся статья оказалась еще и полезной, то буду благодарен вашим пожертвованиям на развитие сайта - кнопка DONATE ниже (любая валюта).

Удачного кодирования!                                                                                                                                                              

Телеграм канал - Full Stack JavaScript Developer
Помочь проекту (любая валюта). DONATE

среда, 27 мая 2020 г.

React . Детальный обзор Context API

React Context API предоставляют механизм для передачи данных через дерево компонентов без передачи реквизитов на каждый уровень вручную.



Нам не нужно передавать данные на каждый уровень, вместо этого мы создаем контекст для компонента более высокого уровня и делаем данные контекста доступными для дочерних или дочерних компонентов. Статья посвящена подробному пониманию концепций React Context.

Друзья, я ранее уже много раз рассказывал вам об использовании реакт-хуков для быстрого, удобного и простого построения ваших приложений. Если вы что-то подзабыли, то welcome к моим постам по - React. Там вы найдете много простых и интересных решений, в частности - полноценное приложение построенное только на функциональных компонентах и реакт-хуках. Стоит посмотреть построение React-Сайта и некоторые мои статьи и переводы на gitHub Там я много пишу о самых распространенных и не очень решениях для построений реакт-приложений.


Когда нужно использовать React Context

В этом разделе мы увидим, когда нам нужно использовать React Context API. API React Context просты в использовании и очень эффективны. Приложение React может состоять из иерархии Компонентов, имеющих отношение Parent-Child, иерархия может иметь несколько уровней.

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



Пример кода:

import React from "react";

export default class GrandParents extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      surName: "Gupta",
    };
  }
  render() {
    return (
      <>
        <h1>This is the Grand Parent Component</h1>
        <Parents surName={this.state.surName} />
      </>
    );
  }
}
function Parents(props) {
  return (
    <div>
      <h2>This is a Parent Component</h2>
      <Children surName={props.surName} />
    </div>
  );
}
function Children(props) {
  return (
    <div>
      <b>Inherited Child Properties from Grand Parents: </b>
      <label>{props.surName}</label>
    </div>
  );
}



Code Sandbox link

В приведенном выше примере у нас есть компонент верхнего уровня «GrandParent», который содержит некоторую строку данных «surName». Этот компонент содержит другой компонент «Parent», которому мы отправляем эту информацию о «surName» в данных «props». Этот «родительский - Parent» компонент не использует эти данные, ему просто нужно передать эти данные следующему дочернему компоненту «Children», а затем этот компонент «Children» использует эту информацию «surName».

Проблема с вышеуказанным кодом

В приведенном выше сценарии данные требуются только на дочернем уровне. Но мы распространяем данные по всей Иерархии, чтобы сделать их доступными на более низком уровне («Children»). На первый взгляд ничего особенного, но представьте, что на месте одного родительского компонента, который просто передает пропсы ниже, не один а десять, а то и двадцать уровней компонентов? Используя контекст, мы можем сократить издержки на передачу данных по всей иерархии, чтобы сделать их доступными для компонентов самого низкого уровня. Далее давайте рассмотрим детали того, как уменьшить издержки на передачу props с помощью React Context.

Работа с контекстом React - React Context

Чтобы решить вышеуказанную проблему, мы можем использовать API React Context.React Context API состоит из:
  1. Context Object

    Чтобы использовать Context в приложении, нам сначала нужно создать объект контекста - Context Object, который способен хранить данные для приложения. Этот объект можно сделать доступным для иерархии для подачи или получения данных. Приведенный ниже код позволит нам создать объект контекста для всей иерархии.

    const FamilyContext = React.createContext({});


  2. Context Provider

    const FamilyProvider = FamilyContext.Provider;

    Context Provider используется для предоставления значения этому объекту контекста - Context Object. Мы можем добавить к контексту, используя этот объект Context Provider.


  3. Context Consumer

    const FamilyConsumer = FamilyContext.Consumer;

    Этот объект потребителя - Context Consumer используется для получения значения контекста и предоставления значения для компонента. Значение, сохраненное в контексте с использованием «Context Provider», может быть получено с помощью объекта Consumer Context.

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


import React from "react";
const FamilyContext = React.createContext({});
export const FamilyProvider = FamilyContext.Provider;
export const FamilyConsumer = FamilyContext.Consumer;

export default class GrandParents extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      surName: "Kolesnikov",
      random: "Text",
    };
  }
  render() {
    return (
      <FamilyContext.Provider value={this.state}>
        <div>
          <h1>Grand Parents Initial Surname: </h1>
          {this.state.surName}
        </div>
        <Parents></Parents>
      </FamilyContext.Provider>
    );
  }
}

function Parents(props) {
  return (
    <div>
      <h2>Inherited Parent Property With "props":</h2>
      <label></label>
      <br />
      <br />
      <br />
      <Children />
    </div>
  );
}

class Children extends React.Component {
  render() {
    return (
      <FamilyConsumer>
        {(context) => {
          return (
            <div>
              <h3>Inherited Child Properties without "props": </h3>
              <label>{context.surName}</label>
            </div>
          );
        }}
      </FamilyConsumer>
    );
  }
}




Code Sandbox link

В приведенном выше коде следует обратить внимание на следующее:

  1. Сверху мы создали Объект контекста (FamilyContext), Объект провайдера (FamilyProvider) и Объект потребителя (FamilyConsumer).
  2. Значение добавляется в контекст в компоненте «GrandParent» с использованием объекта «Провайдер» - Provider Object. Мы используем свойство value для добавления необходимых данных в объект провайдера -Provider Object. Данные не нужно использовать в компоненте «Родитель» - Parent.
  3. Чтобы сделать данные напрямую доступными для компонента Children, мы используем Consumer Object - объект-потребитель (FamilyConsumer). Это сделает данные доступными непосредственно дочерним компонентам.
А если в двух словах, то мы просто взяли от реакта нужные нам части контекста и определили их в самом верху файла:

const FamilyContext = React.createContext({});
export const FamilyProvider = FamilyContext.Provider;
export const FamilyConsumer = FamilyContext.Consumer;


Затем, просто обернули все, что рендерим в корневом компоненте в провайдер, в который и передали пропсы, а в нужном месте (Дочерний компонент) достали их из контекста через функцию.

Все это в коде выделил красным!

PS

В приведенном выше примере данные не нужно передавать по всей иерархии, данные были доступны на верхнем уровне и были непосредственно доступны дочернему элементу с помощью объекта контекста. Отсюда устраняется необходимость передачи данных с использованием «реквизита - props» по всей иерархии.

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

React. Как использовать «useContext» в React Hooks

Хотите оставаться в курсе новинок в области JS-программирования? Подписывайтесь на мой канал, вступайте в группу на Facebook. Если понравившаяся статья оказалась еще и полезной, то буду благодарен вашим пожертвованиям на развитие сайта - кнопка DONATE ниже (любая валюта).

Удачного кодирования!                                                                                                                                                              

Телеграм канал - Full Stack JavaScript Developer
Помочь проекту (любая валюта). DONATE


Хотите освоить самые современные методы написания React приложений? Надоели простые проекты? Нужны курсы, книги, руководства, индивидуальные занятия по React и не только? Хотите стать разработчиком полного цикла, освоить стек MERN, или вы только начинаете свой путь в программировании, и не знаете с чего начать, то пишите через форму связи, подписывайтесь на мой канал в Телеге, вступайте в группу на Facebook.Пишите мне - kolesnikovy70 почта gmail.com