Приложение todo затрагивает все важные части создания любого приложения на основе данных, включая C reate, R ead, U pdate и D elete (CRUD) операций. В этой истории я буду создавать приложение для задач с помощью одного из самых популярных мобильных фреймворков, React Native.

Я буду использовать ReactiveSearch Native, библиотеку с открытым исходным кодом, которая предоставляет компоненты пользовательского интерфейса React Native и упрощает создание приложений, управляемых данными.

Вот что я построю в этой истории:

Загляните в приложение на закусках или на экспо.

Что такое React Native?

Вот что говорят документы:

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

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

Зачем использовать ReactiveSearch? ⚛

ReactiveSearch - это библиотека компонентов пользовательского интерфейса React и React Native с открытым исходным кодом для Elasticsearch, которую я написал в соавторстве с некоторыми замечательными людьми. Он предоставляет множество компонентов React Native, которые могут подключаться к любому кластеру Elasticsearch.

Я написал еще один рассказ на тему Создание GitHub Repo Explorer с помощью React и Elasticsearch, в котором вы можете ознакомиться с кратким обзором Elasticsearch. Даже если у вас не было опыта работы с Elasticsearch, вы сможете прекрасно следить за этой историей.

Настраиваем ⚒

Здесь мы будем использовать версию React Native библиотеки.

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

Для краткости вы можете использовать мой набор данных напрямую или создать его для себя с помощью appbase.io, который позволяет вам создать размещенный индекс Elasticsearch (также известный как приложение).

Все задачи структурированы в следующем формате:

{
  "title": "react-native",
  "completed": true,
  "createdAt": 1518449005768
}

Стартовый проект

Прежде чем мы начнем, я бы порекомендовал установить пряжу. В Linux это можно сделать, просто добавив репозиторий yarn и выполнив команду установки через диспетчер пакетов. На Mac вы должны сначала установить Homebrew, чтобы упростить задачу. Вот документация по установке пряжи для более подробной информации. Следующее, что вы можете установить, это сторож. Это служба просмотра файлов, которая поможет упаковщику, работающему с реакцией, работать без сбоев.

Я установил стартовый проект с помощью create-react-native-app в ветке GitHub здесь. Вы можете скачать zip или клонировать базовую ветку, выполнив следующую команду: 😌

git clone -b base https://github.com/appbaseio-apps/todos-native
  • Затем установите зависимости и запустите упаковщик:
cd todos-native && yarn && yarn start
  • После запуска упаковщика вы можете запустить приложение на своем телефоне с помощью приложения Expo или с помощью эмулятора Android или IOS:

Погружение в код 🏊

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

navigation
├── RootComponent.js         // Root component for our app
├── MainTabNavigator.js      // Tab navigation component      
screens
├── TodosScreen.js           // Renders the TodosContainer    
components        
├── Header.js                // Header component         
├── AddTodo.js               // Add todo input        
├── AddTodoButton.js         // Add todo floating button        
├── TodoItem.js              // The todo item         
├── TodosContainer.js        // Todos main container
api                          
├── todos.js                 // APIs for performing writes
constants                    // All types of constants used in app
types                        // Todo type to be used with prop-types
utils                        // Streaming logic goes here

Давайте разберемся, что входит в базовую комплектацию:

1. Навигация

  • Все необходимые конфигурации для подключения к Elasticsearch находятся по адресу constants/Config.js.
  • Мы используем TabNavigator из react-navigation для отображения экранов задач Все, Активные и Завершено. Это отображается navigation/RootComponent.js. Вы заметите, что RootComponent обертывает все внутри компонента ReactiveBase из ReactiveSearch. Этот компонент предоставляет все необходимые данные дочерним компонентам ReactiveSearch. Вы можете подключить здесь свой собственный индекс Elasticsearch, просто обновив конфигурации в constants/Config.js.

Логика навигации присутствует в navigation/MainNavigator.js. Давайте посмотрим, как это работает. Здесь находятся документы для навигации по вкладкам, если вы хотите на что-нибудь сослаться.

  • Функция TabNavigator принимает два аргумента, первый - это конфигурации маршрута, а второй - конфигурации TabNavigator. В приведенном выше фрагменте мы передаем конфигурации для отображения панели навигации по вкладкам внизу и установки разных значков для каждой вкладки.

2. TodosScreen и TodosContainer

TodosScreen компонент в screens/TodosScreen.js является оберткой нашего основного TodosContainer компонента в components/TodosContainer.js, куда мы будем добавлять различные компоненты для приложения. TodosContainer будет отображать отфильтрованные данные в зависимости от того, находимся мы на вкладке Все, Активно или Завершено.

3. API для создания, обновления и удаления задач.

API-интерфейсы для операций CUD в Elasticsearch представлены в api/todos.js. Он содержит три простых метода add, update и destroy, которые работают с любым индексом Elasticsearch, указанным в constants/Config.js. Важно помнить, что каждый создаваемый нами элемент todo будет иметь уникальное поле _id. Мы можем использовать это _id поле для обновления или удаления существующей задачи.

Для нашего приложения нам понадобится всего три метода для добавления, создания или удаления задач. Однако вы можете найти подробное описание методов API в документации.

Сборка компонентов и пользовательского интерфейса 💻

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

1. Добавление Todos

Мы будем использовать Fab из native-base для рендеринга плавающей кнопки для добавления задач.

Теперь вы можете использовать этот компонент в components/TodosContainer.js.

import AddTodoButton from './AddTodoButton';
...
export default class TodosContainer extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        ...
        <AddTodoButton />
      </View>
    );
  }
}

Как только мы добавим кнопку, мы увидим что-то вроде этого:

Теперь, когда кто-то нажимает на эту кнопку, нам нужно будет показать ввод для добавления задачи. Давайте добавим код для этого в components/AddTodo.js.

Здесь используются основные компоненты TextInput, Checkbox и Ionicons с простыми опорами. Мы используем title и completed из state. Мы будем передавать реквизиты todo, onAdd, onCancelDelete и onBlur из components/TodosContainer.js. Это поможет нам добавить новые задачи или сбросить вид, если вы хотите отменить добавление задач.

Теперь мы можем обновить components/TodosContainer.js, добавив необходимые изменения для рендеринга AddTodo компонента:

Компонент AddTodo отображается внутри компонента ScrollView. Мы также передаем опору onPress в AddTodoButton для переключения состояния и условного отображения компонента AddTodo на основе this.state.addingTodo. Опора onAdd, переданная в AddTodo, также создает новую задачу с использованием add API в api/todos.js.

После нажатия кнопки добавления мы увидим ввод для добавления задачи следующим образом:

2. Отображение Todos

После того, как вы закончите добавление задачи, она будет добавлена ​​в Elasticsearch (который мы настроили в constants/Config.js). Все эти данные можно просматривать в реальном времени с помощью компонентов ReactiveSearch Native.

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

Давайте добавим компонент ReactiveList и получим отображение наших задач. Мы добавим этот компонент в components/TodosContainer.js и необходимые методы для его работы. Вот как будет использоваться ReactiveList:

Мы еще не добавили метод onAllData, но давайте немного разберемся с реквизитами, которые мы здесь использовали:

  • componentId - уникальный идентификатор компонента.
  • defaultQuery: запрос, который будет первоначально применен к списку. Мы будем использовать match_all, чтобы показать все задачи по умолчанию.
  • stream: следует ли передавать новые обновления результатов в потоковом режиме или просто отображать исторические результаты. Установив для этого параметра значение true, мы теперь также слушаем обновления Todo в реальном времени. Логику потоковой передачи мы добавим позже.
  • onAllData - функция обратного вызова, которая получает список текущих задач и потоковой передачи (новые задачи и любые обновления) и возвращает компонент React или JSX для рендеринга. Вот как выглядит синтаксис:

Вы можете подробно прочитать обо всех этих свойствах на странице документации ReactiveList.

Чтобы что-то увидеть, нам нужно вернуть компонент JSX или React из onAllData обратного вызова. Для этого мы будем использовать FlatList React Native, который состоит из компонентов Text. На следующем этапе мы добавим наш пользовательский компонент TodoItem.

3. Добавление TodoItem (ов)

Затем мы создадим отдельный компонент TodoItem для отображения каждой задачи, который будет содержать все необходимые разметки для элемента задачи, такого как CheckBox, Текст и Значок для удаления. Это идет в components/TodoItem.js:

Этот компонент получает todo от своих свойств вместе с onDelete и onUpdate, которые используются для обновления и удаления элемента задачи соответственно. Мы используем их в необходимых местах, используя onPress опору используемых нами компонентов.

Затем мы можем import и использовать компонент TodoItem в нашем onAllData в components/TodosContainer.js. Мы передадим todo как опору вместе с методами API для update и destroy, которые будут использоваться компонентом TodoItem.

4. Обновления потоковых данных

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

В предыдущем разделе мы добавили метод onAllData для компонента ReactiveList. Второй параметр onAllData получает потоковые обновления, которые мы будем использовать, чтобы постоянно обновлять задачи. Вот как обновленный onAllData метод будет выглядеть в components/TodosContainer.js.

Метод mergeTodos присутствует в utils/index.js. Вот как это работает:

streamData получает массив объектов todo при их создании, удалении или обновлении. Если объект обновлен, он содержит ключ _updated, установленный на true. Точно так же, если объект удален, он содержит ключ _deleted, установленный на true. Если объект создан, он не содержит ни того, ни другого. Используя эти точки, мы добавили функцию mergeTodos.

Благодаря этому вы сможете видеть изменения в задачах в реальном времени! Если у вас есть дополнительное устройство / эмулятор, на котором запущено одно и то же приложение, оба будут транслировать новые обновления. 😄

Полезные ссылки

  1. Приложение Todos демо, ссылка на выставку, стартовый проект и окончательный исходный код
  2. Репозиторий ReactiveSearch GitHub ⭐️
  3. ReactiveSearch документы

Надеюсь, вам понравилась эта история. Если у вас есть какие-либо мысли или предложения, дайте мне знать и получайте удовольствие!

Особая благодарность Дхрувдутту Джадхаву за помощь мне с этой историей и приложением Todos. 🙌