[Из песочницы] Создание приложения Sticky Notes с использованием 8base, GraphQL и React


image

Посмотреть демо версию программы здесь.

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

Чтобы создать приложение для заметок, нам потребуется простой стек, практически не требующий бэкенд разработки, и приложение, которое можно будет легко развернуть. Исходя из этих требований, мы выберем стек для приложения. Он выглядит так:
-React - для фронтенд разработки. Это популярная библиотека для создания пользовательских интерфейсов, она может быть легко развернута на нескольких платформах, таких как Now и Netlify.
-8base GraphQL — слой базы данных для нашего приложения. Здесь мы будем хранить и читать запросы в нашем приложении. С 8base не нужно создавать и поддерживать бэкенд для приложения.

Я успешно создал простое приложение, используя эти инструменты. В этой статье мы рассмотрим процесс создания этого приложения и настройки бэкенда, работающего на платформе 8base.

image

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

Чтобы следовать инструкциям, требуется базовое понимание React и Node.js. Перед началом работы убедитесь пожалуйста, что у вас установлены Node и npm/yarn.

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

Платформа 8base предлагает широкий выбор функций, помогающих разработчикам создавать приложения быстрее и проще. С 8base вы можете легко организовать бэкенд своего приложения без написания кода. Используя платформу 8base, вы можете создать свой бэкенд с помощью простого графического интерфейса, который позволяет выполнять такие действия как:

  • Определять вашу схему данных: создать таблицы / отношения таблиц.
  • Загружать файлы.
  • Определять права доступа и роли авторизации.
  • Управлять различными проектами, используя воркспейсы.
  • Проектировать запросы с помощью API Explorer (на основе GraphQL).

В этом руководстве мы увидим, как использовать 8base для быстрой настройки серверной части и обработки данных с помощью GraphQL API. Наше фронтенд приложение будет построено с использованием React и будет взаимодействовать с сервером с помощью GraphQL.

Чтобы начать использовать 8base, выполните следующие действия:

1. Создайте аккаунт на 8base. Это бесплатно.

image

2. После завершения регистрации нажмите кнопку Data Builder, чтобы перейти на страницу Data, и нажмите New Table, чтобы начать настройку бэкенда.

image

3. После загрузки новой таблицы вы попадете в схему и сможете начать определять поля. Давайте отметим пару вещей. Слева вы увидите System Tables и Your Tables.

Каждый новый воркспейс 8base автоматически поставляется с несколькими встроенными таблицами. Эти таблицы используются для таких вещей, как Файлы, Настройки и Разрешения, и все они доступны через API-интерфейс 8base GraphQL.

4. Идем дальше и создаем таблицу Notes, которая состоит из следующих полей:

title: тип поля Text. Здесь будет название заметки.
text: тип поля Text. Это поле будет содержать тело заметки.
Наша схема довольно проста и используется для достижения тех возможностей, которые мы пытаемся реализовать.

image

5. Затем скопируйте URL-адрес API эндпоинта (доступен слева внизу) — это основная линия связи между клиентской и серверной частью вашего приложения.

image

6. Наконец, для целей данного руководства мы по умолчанию разрешим открытый доступ для Гостей, так чтобы проверка подлинности была не обязательна. Чтобы разрешить гостевой доступ к новой таблице Notes, перейдите в Settings > Roles > Guest и установите соответствующие флажки в разделе Notes. Всем неавторизованным пользователям, которые получают доступ к вашей конечной точке API, по умолчанию предоставляется роль Гостя. Авторизация в этом руководстве не рассматривается. Здесь можно подробнее ознакомиться с тем, как с ней работать.

image

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

Начинаем

Я создал стартовый проект для легкой настройки и уменьшения оверхеда, так чтобы статья в основном описывала начало работы с 8base и GraphQL. Скелет приложения уже настроен, в том числе стили и структура проекта. В ветке starter доступны следующие возможности:

  1. Компонент формы заметки для создания заметки.
  2. Компонент заметки, который отображает детали одной заметки.
  3. Компонент списка заметок, отображающий список доступных заметок.

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

git clone -b starter https://github.com/HackAfro/note-app.git

Откройте папку и установите зависимости проекта, выполнив следующую команду:

npm install

Запустите сервер приложений React, запустив npm start в терминале в корневой папке вашего проекта.

Подключение к бэкенду 8base с помощью GraphQL

Теперь, когда наше начальное фронтенд запущено и работает, следующим шагом является настройка клиента для взаимодействия с бэкендом 8base с использованием GraphQL. Полезная библиотека для помощи в соединении — apollo-boost; она предоставляет клиент для подключения к бэкенду GraphQL с помощью URI. URI — это эндпоинт, предоставляемый 8base. Давайте обновим файл index.js, чтобы настроить ApolloClient.

import React from "react";
import ReactDOM from "react-dom";
import { ApolloProvider } from "react-apollo";
import ApolloClient from "apollo-boost";
import * as serviceWorker from "./serviceWorker";
import "./index.css";
import App from "./App";
const client = new ApolloClient({
  uri: "<YOUR_8BASE_ENDPOINT>"
});
ReactDOM.render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  document.getElementById("root")
);
serviceWorker.unregister();

ApolloClient принимает объект со свойством uri в качестве аргумента; при этом клиент дает нам доступ для получения, обновления и удаления данных с использованием предоставленного uri. Обязательно замените значение <YOUR_8BASE_ENDPOINT> на фактическую конечную точку.

Затем мы оборачиваем приложение в ApolloProvider, который принимает проп client. ApolloProvider загружает схему таблицы 8base, которая дает вам доступ ко всем свойствам модели данных в вашем фронтенд коде.

Получение и отображение заметок

Чтобы получить заметки c бэкенда, мы напишем GraphQL запрос для получения заметок, хранящихся в 8base. Давайте начнем, обновив файл App.js.

Добавьте следующие импорты туда, где вы найдете комментарий TODO — 1:

import gql from "graphql-tag";
import { graphql } from "react-apollo";

Они будут полезны для создания GraphQL запросов и передачи пропсов в компонент App для получения заметок. Далее нам нужно добавить запрос для получения заметок с серверной части. Обновите NOTE_LIST_QUERY, чтобы он был похож на фрагмент ниже:

const NOTE_LIST_QUERY = gql`
      query {
        notesList {
          items {
            id
            title
            text
          }
        }
      }
    `;

Если вы не уверены в ваших запросах, вы всегда можете протестировать их в 8base API explorer. Давайте проверим приведенный выше запрос.

Если вы выполните этот запрос в своем проводнике, скорее всего вам вернется пустой массив, потому что вы не создали никаких заметок. Мы можем легко создавать заметки, используя панель инструментов 8base. Перейдите по ссылке data на боковой панели и следуйте инструкциям на скриншотах ниже:

image

Мы получим id, title и text из элементов notesList. Далее мы подготовим компонент App для использования заметок, получаемых из запроса. Наконец, мы будем использовать graphql HOC (Higher Order Component), чтобы связать запрос с компонентом App. Функция принимает строку запроса и параметры конфигурации.
// TODO — 3

  export default graphql(NOTE_LIST_QUERY, {
      props: (result) => {
        const { data } = result;
        const { loading, refetch } = data;
        let notes = [];
        if (data && data.notesList) notes = data.notesList.items;
        return {
          loading,
          notes,
          refetch,
        };
      },
    })(App);

Замените существующую строку экспорта под комментарием TODO—3 фрагментом выше.

Функция graphql возвращает “enhancer” функцию, которая расширит любой переданный в нее компонент, возможностями GraphQL. Это соответствует паттерну компонентов высокого порядка, который также используется функцией connect в response-redux.

Используя функцию graphql(), мы можем обратится к эндпоинту GraphQL. В качестве первого параметра он принимает запрос (NOTE_LIST_QUERY), второй — config, возвращаемое значение — HOC, который должен выполняться с требуемым компонентом в качестве аргумента. Во фрагменте мы передаем значение свойства data.noteList новой переменной notes. Возвращая это значение, мы можем получить к нему доступ внутри компонента как props.notes, а состояние загрузки — как props.loading.

Метод refetch будет очень полезен, чтобы мы могли достичь чего-то близкого к обновлению в реальном времени. Мы будем вызывать функцию после каждой мутации, чтобы гарантировать, что данные в приложении всегда синхронизированы с бэкендом 8base.
Если вы перейдете на localhost:3000, вы увидите только что созданную заметку. Нам нужно иметь возможность создавать заметки, не посещая панель инструментов 8base, это означает переход на следующий уровень GraphQL…. Мутации!

Создание заметок

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

В предыдущем разделе мы выполняли запрос для получения заметок с бэкенда, в этом разделе мы будем выполнять мутации для сохранения новых заметок, мутация имеет сходство с запросом, с той лишь разницей, что мутация вызывается всякий раз, когда есть необходимость изменить данные. После создания таблиц в 8base запросы и мутации для этой таблицы становятся легко доступными в API проводнике; поэтому мы всегда можем попасть туда, если сомневаемся в том, как мутация должна быть структурирована.

Давайте посмотрим, как выглядит мутация для создания заметок в API проводнике. Перейдите на панель инструментов 8base и нажмите на API Explorer на боковой панели.

В проводнике API нажмите на ссылку mutation, как показано выше. Это покажет все доступные мутации. Ищите то, что отвечает за создание заметок:

image

На скриншоте показано, что имя мутации — noteCreate, и она принимает один аргумент типа NoteCreateInput. NoteCreateInput — определяет тип тела запроса, необходимого для создания заметки.

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

Откройте src/components/note-form/index.js, добавьте следующие импорты, где у вас есть комментарий TODO 1.:

import gql from "graphql-tag";
import { graphql } from "react-apollo";

Далее мы объявим мутацию, обновим переменную NOTE_MUTATION и назначим ей новое значение, подобное приведенному ниже фрагменту:

const NOTE_MUTATION = gql`
      mutation NoteCreate($data: NoteCreateInput!) {
        noteCreate(data: $data) {
          id
        }
      }
    `;

Далее мы свяжем мутацию с компонентом с помощью функции graphql. Замените строку export в файле с фрагментом ниже:

export default graphql(NOTE_MUTATION, {
      name: "noteCreate"
    })(NoteForm);

Таким образом, graphql функция передает именованную функцию noteCreate, которая будет использоваться для выполнения мутации create. Давайте используем функцию noteCreate для создания заметки при отправке формы.

Перейдите к комментарию TODO 4 и обновите функцию submit, чтобы она была похожа на фрагмент ниже:
// TODO — 4

   const submit = async note => {
        const res = await noteCreate({ variables: { data: note } });
        if (res.data.noteCreate.id) {
          setNote({ title: "", text: "" });
          refetch()
        }
    };

В приведенном выше фрагменте мы использовали функцию noteCreate для выполнения мутации create в таблице заметок. Аргумент, переданный функции, является объектом, содержащим variables и тело data.

Мы ждем, пока запрос будет завершен, затем проверяем его успешность, найдя id в теле ответа. Затем мы сбрасываем состояние note и refetch. Я упоминал функцию refetch ранее в этой статье, но позвольте мне обновить вашу память. Refetch заставляет ваш компонент повторять запрос, который вы определили в функции graphql().

Теперь все готово к тестированию. Перейдите на localhost:3000, заполните форму и наслаждайтесь результатом.

Удаление заметок

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

  1. Пользователь нажимает на кнопку удаления.
  2. Появляется окно подтверждения — это уменьшает количество злых пользователей, очень полезно.
  3. Остается совершить поступок — удалить заметку.

Настройка для удаления заметок находится в файле src/note-card/delete-button.js. Откройте файл и добавьте следующие импорты в верхней части файла. В частности, ниже, где находится TODO 1:

import gql from 'graphql-tag';
import { graphql } from 'react-apollo';

Затем запишите мутацию удаления и присвойте ее переменной DELETE_MUTATION. Это должно выглядеть примерно так, как показано ниже:

const DELETE_MUTATION = gql`
      mutation DeleteNote($data: NoteDeleteInput!) {
        noteDelete(data: $data) {
          success
        }
      }
    `;

Далее мы свяжем мутацию с компонентом с помощью graphql функции. Замените строку export в файле фрагментом ниже:

export default graphql(DELETE_MUTATION, {
      name: 'deleteNote',
    })(DeleteButton);

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

Перейдите к функции onDeleteClick в компоненте, поместите следующий фрагмент внутри функции:

const onDeleteClick = async () => {
      const data = {
        id: noteId,
      };
      const remove = window.confirm('Are you sure you want to delete this note?');
      if (remove) {
        await deleteNote({ variables: { data } });
        refetch();
      }
    };

При нажатии кнопки удаления, в теле объекта data мы присваиваем полю id значение noteId, а затем показываем пользователю сообщение с подтверждением, однозначно заявляя, что мы намерены удалить эту заметку навсегда. Если пользователь делает как задумано и решает продолжить, мы вызываем функцию deleteNote, чтобы сделать мутацию удаления. Когда это завершено, нужно приложение.

Вот как это должно выглядеть. Перейдите по адресу localhost:3000 и попытайтесь удалить заметку:

image
Вы можете найти демо-версию этого приложения здесь.

Заключение

Я уверен, что вы неплохо провели время, создавая это приложение, мы посмотрели, как писать запросы для получения данных с серверной части 8base, а также как писать мутации создания и удаления. 8base как платформа относительно проста в навигации и предлагает интуитивно понятный пользовательский интерфейс. Я провел ночь, выясняя это. Вы можете заполнить пропущенную дыру, узнав, как писать update мутации и добавить возможность редактировать заметку. Я уверен, что пользователи будут довольны. Вы также можете просмотреть их официальную документацию, чтобы получить больше информации о платформе. Исходный код приложения вы можете найти здесь.

Теги:

Source: habr1