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

1 комментарий:



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