Создайте полнофункциональное приложение React с доступом к базе данных за считанные минуты

TL; DR: В этом посте мы создаем полнофункциональное приложение React с нуля с помощью Infrastructure-Components. Мы берем вводимые пользователем данные и сохраняем их в базе данных (DynamoDB) через интерфейс GraphQL. Мы также получаем данные из базы данных и отображаем их. Мы рассмотрим два способа работы с базой данных:

  1. С компонентами React-Apollo (<Query/> и <Mutation/>)
  2. С крючками React-Apollo

Определите архитектуру вашего приложения

Мы настраиваем наш проект с помощью Инфраструктура-Компоненты. Эти React-компоненты позволяют нам определить нашу инфраструктурную архитектуру как часть нашего React-приложения. Нам больше не нужны никакие другие конфигурации, такие как Webpack, Babel или Serverless.

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

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

Проекты на базе Инфраструктура-Компоненты имеют единую компоненту верхнего уровня. Это определяет архитектуру вашего приложения. Подкомпоненты (дочерние элементы) уточняют поведение приложения и добавляют функции.

Поскольку мы создаем приложение с полным стеком, мы используем <ServiceOrientedApp/>-component как наш компонент верхнего уровня. Мы экспортируем его по умолчанию в наш файл точки входа (src/index.tsx).

<ServiceOrientedApp/> - интерактивное веб-приложение. Он поддерживает использование маршрутов, сервисов и базы данных.

  • <Route/> - это страница вашего приложения. он работает как <Route/> в react-router. Мы можем отобразить что угодно, от простого <div/> до страницы, полной компонентов React. Вот учебник по работе с маршрутами.
  • <Service/> определяет функцию, которая выполняется на стороне сервера. Он может иметь один или несколько <Middleware/>-компонентов в качестве дочерних. <Middleware/> работает как промежуточное ПО Express.js.
  • <DataLayer/> добавляет в ваше приложение базу данных NoSQL (DynamoDB).
  • <Envrionment/> создает среду выполнения вашего приложения, которая позволяет запускать и развертывать его.

Начать

Вы можете настроить свой проект тремя способами:

После того, как вы установили зависимости (запустите npm install, если вы клонировали или загрузили файлы), вы можете собрать проект с помощью одной команды:
npm run build. Потом:

  • npm run {your-project-name} запускает ваше приложение React локально (режим hot-dev, без серверной части и базы данных). Режим hot-dev особенно полезен при разработке пользовательского интерфейса. Это все визуальные вещи. В этом режиме изменения в исходном коде вступают в силу немедленно. Однако этот режим не запускает backend-сервисы и базу данных.
  • npm run start-{your-env-name} запускает весь программный стек локально. Он запускает пользовательский интерфейс, службы и базу данных. Но вам придется перезапустить его, когда вы измените исходный код.
    Примечание (1): Для запуска базы данных в автономном режиме требуется Java 8 JDK. Вот, как вы можете установить JDK.
    Примечание (2): локальной базе данных требуется некоторое время для запуска. В результате первый запрос занимает довольно много времени. Последующие запросы выполняются быстрее.

Настройте структуру данных

<DataLayer/>-компонент создает Amazon DynamoDB. Это база данных типа "ключ-значение" (NoSQL). Он принимает <Entry/>-компонентов как дочерние элементы. <Entry/> описывает тип элементов в вашей базе данных. Это абстрактное описание ваших данных. Это не случай. Экземпляр <Entry/> - это элемент.

<Entry/> определяет имена своих primaryKey и rangeKey. Он также содержит плоский объект Javascript в виде data-field.

Допустим, мы хотим хранить опубликованные статьи в базе данных. Следующее <Entry/> описывает структуру article-пунктов.

  • Мы определяем имена для наших primaryKey и rangeKey. Вы можете использовать любое имя, кроме некоторых ключевых слов DynamoDB, которые вы можете найти здесь. Список довольно длинный. Так что лучше используйте комбинированные слова, например articleid, а не id.
  • Элемент (также известный как дискретный экземпляр <Entry/>) должен предоставлять значения для primaryKey и rangeKey. Эти значения обязательны. article-элемент должен иметь articleid и title.
  • Элемент может (необязательно) предоставлять значения для ключей в поле data. article-элемент может иметь articlelink.
  • Комбинация primaryKey и rangeKey описывает уникальный элемент в базе данных. Не может быть второго article с таким же articleid и таким же title. С точки зрения базы данных было бы нормально, если бы у двух article был одинаковый articleid, тогда как у них был бы другой title (или наоборот).
  • Не должно быть других <Entry/> с такими же именами primaryKey и rangeKey. Одно имя может совпадать, но не оба одновременно. У нас не может быть другого <Entry/> в нашей базе данных с primaryKey="articleid” и rangeKey="title".

Допустим, мы хотим, чтобы в наших статьях было tag. tag - это такое слово, как «программирование», «реагирование» или «javascript». Он описывает содержание article. article может иметь любое количество tag. Но каждый tag может быть только один раз.

Следующее <Entry/> описывает структуру tag-пунктов.

Помнить. Комбинация primaryKey и rangeKey описывает уникальный элемент в базе данных. Следовательно, article может иметь tag только один раз. Но article может иметь любое количество tag. И разные articles могут иметь одинаковые tag.

Работа с данными

Хватит подготовки! Давай поработаем с данными.

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

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

Добавить статью

Начнем с пустой базы данных. Давайте изменим это, добавив article.

Пользовательский интерфейс следующего React-компонента представляет собой простую форму. Он имеет два поля <input/> и поле <button/>.

Каждый <input/> подключается к локальному состоянию с помощью React-ловушки. Это состояние сохраняет введенные значения в интерфейсе (вкладка браузера). Он исчезнет, ​​если вы обновите страницу. Он еще не хранится в базе данных.

<button/> триггеры сохраняют значения в базе данных. <button/> выполняет функцию postMutation, которую получает от компонента <Mutation/>.

<Mutation/>-компонент творит всю магию. Импортируем из react-apollo. Вот описание этого компонента.

<Mutation/>-компонент принимает в качестве свойств: mutation-query и необязательный context. Мы получаем и то, и другое из функции setEntryMutation. Мы внедряем эту функцию в props нашего компонента через «Компонент высшего порядка» (HOC) withDataLayer.

Параметры позволяют нам описать элемент, который мы хотим добавить:

  • id указывает <Entry/>. Чтобы создать article, мы предоставляем id <ArticleEntry/>.
  • объект Javascript с данными элемента. Сюда входят значения primaryKey и rangeKey. Ключи этого объекта Javascript соответствуют именам, указанным в файле <Entry/>.

В нашем примере мы берем значения title и articlelink из <input/>s. Мы используем UUID как articleid.

withDataLayer-HOC добавляет две функции к props, которые мы можем передать в <Mutation/>-компонент.

  • setEntryMutation (который мы здесь используем) хранит элемент. Он добавляет новый элемент, если он еще не существует с указанной комбинацией primaryKey и rangeKey. Он перезаписывает элемент, если он имеет ту же комбинацию primaryKey и rangeKey.
  • deleteEntryMutation удаляет элемент из базы данных.

Обе функции принимают одинаковые параметры.

Показать список статей

Теперь давайте отобразим статьи, которые мы сохранили в нашей базе данных.

Мы используем <Query/>-компонент, который мы импортируем из react-apollo. Вот описание этого компонента.

<Query/>-компонент принимает в качестве свойств: query и необязательный context.

withDataLayer-HOC предоставляет следующие функции props, которые мы можем передать <Query/>-компоненту.

  • getEntryQuery извлекает один элемент. Нам нужно указать id для <Entry/> и значения primaryKey и rangeKey элемента.
  • getEntryListQuery получает список элементов. Нам нужно указать id из <Entry/> и значение либо primaryKey, либо rangeKey. Возвращаем все предметы с указанной стоимостью.
  • getEntryScanQuery получает список элементов. Мы указываем только id из <Entry/>. Мы можем (необязательно) предоставить диапазон (массив Javascript) нижнего и верхнего пределов либо primaryKey, либо rangeKey.

В нашем примере мы хотим получить все статьи. Поскольку у нас нет ни primaryKey, ни rangeKey, мы используем функцию getEntryScanQuery. Мы предоставляем id из <ArticleEntry/> в качестве параметра. Это извлекает все articles из базы данных.

Компонент <Query/> предоставляет своим дочерним элементам три значения: loading, data и error. Эти значения представляют текущее состояние запроса к базе данных.

  • Пока выполняется запрос, определяется loading.
  • Когда запрос возвращается с ошибкой, error содержит сообщение.
  • Когда запрос выполнен успешно, определяется data. Это объект Javascript. Ключ, который содержит наш список article, - scan_article. Этот ключ является результатом того типа запроса, который мы используем (scan), и id из <ArticleEntry/>.

Добавить тег к статье

Теперь давайте добавим теги к статьям, которые есть в нашей базе данных. Мы могли бы сделать это с помощью <Mutation/>-компонента. Но давайте воспользуемся другим способом: React-хуками.

Пользовательский интерфейс содержит <input/> и <button/>. <input/> подключается к местному государству. Как и раньше.

<button/> триггеры сохраняют значения в базе данных. Так же, как мы делали это раньше, снова.

Разница в том, как мы создаем функцию, которая будет запускаться. На этот раз мы используем функцию createSetMutation (используется для добавления или изменения элемента), которую withDataLayer вводит в наш props. Эта функция принимает функцию useMutation, которую мы импортируем из "@apollo/react-hooks".

В остальном, опять же. Мы предоставляем id <Entry/> и значения primaryKey (articleid) и rangeKey (tag).

Мы получаем articleid от родителя компонента.

Если вы хотите удалить элемент из базы данных, вы можете использовать функцию createDeleteMutation.

Показать тег

Конечно, мы хотим показать теги article. И ты прав. Мы также можем использовать React-хуки для запроса данных.

В следующем коде показан article-компонент.

Этот компонент показывает детали article, которые мы получаем как props от родительского компонента. С articleid мы запрашиваем назначенные tags.

withDataLayer вставляет функцию createQuery в наш props. Это принимает функцию useQuery как параметр, который мы импортируем из "@apollo/react-hooks".

Остальное должно показаться знакомым. Мы используем getEntryListQuery от withDataLayer. На этот раз у нас есть значение primaryKey. Итак, мы предоставляем объект Javascript с одним ключом. Это имя primaryKey (articleid). Присвоенное значение - это articleid, которое мы ищем.

Как и <Query/>-компонент, React-hook также предоставляет три значения: loading, error и data. Они ведут себя точно так же, как в нашем примере выше.

На этот раз вы можете найти список tag в объекте с ключом list_tag_articleid. Этот ключ является результатом того типа запроса, который мы используем (list), id из <Entry/> (tag) и примененного фильтра (articleid).

Посмотрите свою базу данных в действии

Если вы еще не запустили приложение, сейчас самое время сделать это: npm run start-{your-env-name}.

Вы даже можете развернуть свое приложение в AWS с помощью одной команды: npm run deploy-{your-env-name}. (Не забудьте указать учетные данные AWS в .env-файле).

Поддержка и ресурсы

Вы можете делать много замечательных вещей с помощью серверной базы данных. Может быть, вы хотите добавить в свое приложение backend-сервисы? Этот пост показывает, как их добавлять и как вызывать из них свою базу данных.

Хотите стать полноценным разработчиком React?

С React вы можете разделить контент, стиль, макет, состояние и инфраструктуру вашего приложения.

Вы найдете исходный код этого примера в этом репозитории GitHub.

Инфраструктура-Компоненты находятся в активной разработке. Если вы обнаружите ошибку, ваше развертывание выдает ошибку или когда вам нужна какая-либо поддержка, сообщите об этом на странице https://spectrum.chat/infrastructure. Спасибо!

Документация более подробно описывает, как использовать Infrastructure-Components.

Компоненты инфраструктуры - с открытым исходным кодом! Вот репозиторий GitHub.