Как создать простой счетчик и приложение для торгового автомата с помощью хуков React

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

Мы здесь, чтобы поговорить о крючках, так что давайте приступим к делу.

Прежде всего, что такое крючки ??

Справедливый вопрос. Компоненты лежат в основе библиотеки React, и есть два основных способа их написания. Либо как базовый компонент класса или функциональный компонент.

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

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

С добавлением хуков в этом больше нет необходимости, поскольку функциональные компоненты теперь буквально могут «подключаться» к открытым методам React, таким как useState и useEffect которые мы собираемся подробно изучить.

Теперь, когда мы это убрали, давайте посмотрим на это в коде.

Простой счетчик

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

реагирующий счетчик с хуками

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

import React, { useState } from 'react';
import { render } from 'react-dom';
import './styles.css'

const Counter = () => {
 const [count, setCount] = useState(0);
 return (
   <div id="counter">
    <div id="wrapper"></div>
    <header id="counter-header">
      <div id="header-wrapper"></div>

      // The fun stuff
      <button className="cbtn" onClick = {(e) => { if(count > 0) setCount(count - 1)}
       } >-</button>

      <h1>Simple Counter</h1>

      <button className="cbtn" onClick = {(e) => { setCount(count + 1)}}>+</button>

    </header>
    <p className="count">{count}</p>
    <p className="label">Off the hooks!!!</p>
   </div>
 )
}

render(<Counter />, document.getElementById('root'));

Так же, как мы импортировали Составная часть в первой строке вместо этого мы добавляем Хук useState. Затем используется деструктурирующий оператор для установки внутреннего состояния.

const [count, setCount] = useState(0);

Первая переменная — считать, на конструкции есть ценность и второй setCount — это имя функции, которую вы позже будете использовать для обновления значения — вы можете называть ее так, как считаете нужным.

Окончательно, использование состояния справа от оператора принимает то, что выглядит как аргумент, но на самом деле является начальным значением ключа состояния. Итак, на простом английском языке:

Используя обработчик состояния, создайте переменную с именем count и свяжите функцию с именем setCount, которая будет отвечать за обновление ее значения. Тем временем установите начальное значение count на 0

Затем мы добавляем прослушиватели событий на кнопки и для каждой используем setCount обновить считать значение соответственно

<button className="cbtn" onClick = {(e) => { if(count > 0) setCount(count - 1)}}>
-
</button>

<h1>Simple Counter</h1>

<button className="cbtn" onClick = {(e) => { setCount(count + 1)}}>
+
</button>

Вот он, простой пример 🙂 Теперь давайте посмотрим на что-то более сложное, что позволит нам воспользоваться преимуществами нескольких методов жизненного цикла внутри функционального компонента.
Перейдите по ссылке ниже, чтобы редактировать и обновлять по своему усмотрению.

Торговый автомат

Если вы читали некоторые из моих статей, возможно, вы сталкивались с моим JavaScript — серия из 28 актуальных вопросов. Одной из задач является создание «упрощенного» торгового автомата.
Вы можете прочитать больше об этом и, безусловно, попробовать его, перейдя по ссылке ниже.

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

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

export default function VendingMachine( inventory ) {

  var drinks = inventory || null;

  if (!drinks) {
    throw new Error("No inventory: Cannot add a new VM");
  }

  const drinksKeys = Object.keys(drinks);

  var sale = function(pid) {
    if (!drinks[pid]) {
      return;
    }

    if (drinks[pid].stock > 0) {
      drinks[pid].stock--;
      return 1 ${drinks[pid].name} - Thank you, come again!!;
    } else {
      drinks[pid].stock = 0;
      return ${drinks[pid].name} is out of stock :( Come back tomorrow;
    }
  };

  var stock = function() {
    const total = drinksKeys.reduce((c, n) => c + drinks[n].stock, 0);
    return total;
  };

  return Object.freeze({ sale, stock });
}

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

{
  "1": {
    "name": "Mango Juice",
    "stock": 2
  },
  "2": {
    "name": "Banana Smoothies",
    "stock": 2
  },
  "3": {
    "name": "Guava Mix",
    "stock": 1
  },
  "4": {
    "name": "Citrus Blend",
    "stock": 3
  }
}

Предположим, что этот объект исходит из HTTP-вызова. В сценарии компонентов на основе классов мы, вероятно, использовали бы компонентдидмаунт метод жизненного цикла для выполнения запроса и обновления состояния. В случае функционального компонента мы подключимся к использованиеЭффект способ сделать это.

Теперь давайте установим несколько правил/целей, которые мы хотим, чтобы наш компонент React выполнял:

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

Начальная настройка

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

import React, { Fragment, useState, useEffect} from 'react';
import { render } from 'react-dom';
import VendingMachine from './FunModules/VendingMachine'; const LocalVM = () => { // functional logic here return ( <Fragment> // view logic here </Fragment> );
} render(<LocalVM />, document.getElementById('root'));

Как и в случае с простым счетчиком, мы импортируем использование состояния но и использованиеЭффект а также Фрагмент.

Мой личный лайк на Фрагмент насколько легко это позволяет нам выбирать, хотим ли мы добавлять дополнительные теги в DOM или нет — очень мощно.

Последняя строка импорта просто дает нам наш Модуль ВМ. Независимо от того, работаю ли я над проектом Angular или React, я обычно создаю папку с утилитами на чистом Vanilla JS, которые легко повторно использовать либо в фреймворке, либо в библиотеке.

Декларируем наши государственные ценности

Синтаксис состояния в компоненте класса представляет собой объект ключ-значение. Мы определенно могли бы повторить тот же самый шаблон здесь, но то, что он очень интересный и гибкий с использование состояния ловушка заключается в том, что вы можете установить каждое отдельное состояние, которое хотите отслеживать.

Давайте проиллюстрируем это в нашем разделе функциональной логики

// functional logic here
const [vm, setVM] = useState({});
const [loading, isLoading] = useState(true);
const [data, setData] = useState({});
const [message, setMessage] = useState("...");
const [stock, setStock] = useState(0);

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

Однако, чтобы быть предельно ясным, это то, что будет обрабатывать каждый:

  1. вм будет локальным экземпляром нашего торгового автомата и запускается как пустой объект
  2. загрузка — логическое значение, которое по умолчанию имеет значение true и будет иметь значение false, когда пользовательский интерфейс виртуальной машины будет готов к отображению.
  3. данные это объект инвентаризации, который мы вернем из нашего вызова HTTP-запроса
  4. сообщение будет использоваться для отображения статуса успеха или отсутствия на складе
  5. и наконец запас будет отображать начальный подсчет общего запаса напитков и обновлять это число каждый раз, когда совершается покупка.

Запрос инвентаря

Теперь самое интересное, где мы можем воспользоваться преимуществами использованиеЭффект чтобы обернуть наш HTTP-запрос.

useEffect( () => 
{
      fetch('
      .then( response => response.json())
      .then ( data => {
        setData(data);
        setVM(VendingMachine(data));
        isLoading(false);
      });
      // return function statement when component unmounts
  }, 
[] // empty array as second argument to ensure the effect runs once
);

Крючок обвивает нашу принести позвоните и как только мы получим ответ, setData обновляет данные государство и setVM прикрепляет экземпляр торгового автомата с новым инвентарем к нашему вм государство. Обратите внимание, что мы не добавили обработку ошибок в наш принести призыв к краткости.

Код добавляет два очень важных комментария, касающихся управления жизненным циклом. Чрезвычайно важно понимать, что использованиеЭффект является эквивалентом ComponentDidMount, ComponentDidUpdate и ComponentWillUnmount комбинированные методы жизненного цикла

Если мы не передаем пустой массив в качестве второго аргумента, «эффект» будет запускаться каждый раз при обновлении компонента. Это было бы здорово для определенных случаев использования, но в этом конкретном случае мы бы говорили нашему компоненту, чтобы он загружал и устанавливал торговый автомат каждый раз, когда что-то обновлялось в пользовательском интерфейсе.

Пустой массив в качестве второго аргумента помогает нам предотвратить это, делая его один и сделано дело.

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

Я настоятельно рекомендую прочитать больше о тех, кто на Страница документации React.

Рендеринг пользовательского интерфейса наконец

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

return (
    <Fragment>
      {
        loading ? 

        <p>loading...</p>

        : 

        <div>
          // loading is done put the VM interface here
        </div>  
      }
    </Fragment>
  );

Давайте также добавим две вспомогательные функции непосредственно перед использованиеЭффект блок, который позволит использовать чистый способ вызова распродажа а также запас методы виртуальной машины

const sale = (pid) => {
  return vm.sale(pid);
}

const getStock = () => {
  return vm.stock();
}

Когда все готово, давайте добавим последнюю часть пользовательского интерфейса в ложный раздел троичного оператора.

return (
    <Fragment>
      {
        loading ? 
        <p>loading...</p>
        : <div>
            <h3>Pick a fresh drink and enjoy</h3>
            <p>{message}</p>
            <br />
            <div>
                {Object.keys(data).map(d => {
                return <button key={d} id={d} onClick={e => {
                    setMessage(sale(e.target.id));
                  }}>{data[d].name}</button>
                })}
                <br /><br />
                <small>VM current stock: {getStock()}</small>
            </div>
        </div>  
      }
    </Fragment>
  );

Итак, если мы идем сверху вниз в последнем блоке, мы по сути:

  • Ставим реактивный сообщение нить. Это обновляется каждый раз, когда мы нажимаем одну из следующих кнопок.
  • С использованием данные объект, который мы циклически ключи и динамически создайте пользовательский интерфейс кнопок.
  • Каждая кнопка получает прикрепленный к ней прослушиватель событий и передает купленный идентификатор или pid к местному распродажа функция.
  • Действие завернуто в setMessage вызов, который обновляет наш сообщение строка с правильным успехом или отсутствующая строка
  • Окончательно получить запас будет вызываться изначально и каждый раз, когда компонент обновляется, чтобы дать обновленное значение количества запасов

Давайте посмотрим это в действии

Приложение для торговых автоматов React с крючками

И если у вас есть Инструменты разработчика React расширение, установленное здесь, является очень гладким представлением нашего пользовательского интерфейса внутри React DOM.

реагировать-dom-local-vmReact DOM — рендеринг LocalVM

Вывод

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

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

Я не могу достаточно рекомендовать эту жемчужину статьи Ааюш Джайсвал :
10 хуков React, которые вы должны иметь в своем наборе инструментов

Антонин Янушка также составил хорошую шпаргалку по Hooks:
Полная шпаргалка по React Hooks

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

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

Спасибо, что дочитали до этого момента, и не забудьте «подцепить» нескольких друзей, поделившись статьей 😉

Похожие записи

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

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