Отредактировано 07.02.2019: React Hooks теперь является стабильной функцией React версии 16.8.0. В этом руководстве теперь используется версия 16.8.1.

Отредактировано 21.02.2019: Я загрузил демонстрацию на страницы GitHub: https://brookslybrand.github.io/react-indexeddb-example/

Вдохновение

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

Во время одного из наших начальных сеансов обнаружения мы поняли, что наше приложение должно работать полностью в автономном режиме. Более того, поскольку наша целевая аудитория будет заполнять множество форм в нашем приложении, и они могут несколько раз терять соединение при его использовании, данные формы должны быть постоянными. Наконец, мы создаем прогрессивное веб-приложение (PWA), поэтому все это нужно делать в браузере с использованием javascript.

Когда я начал исследовать, возможно ли вообще наше приложение работать в автономном режиме, я быстро обнаружил IndexedDB API. Я был взволнован, узнав все об этом инструменте и о том, как использовать диск из браузера для сохранения изменений, которые пользователь внесет в форму, даже когда они отключены.

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

Вы можете проверить мою первоначальную попытку здесь.

Позже, когда я читал документацию MDN по IndexedDB API, я понял, что упустил важное замечание:

Примечание. IndexedDB API - это мощный инструмент, который может показаться слишком сложным для простых случаев. Если вы предпочитаете простой API, попробуйте библиотеки, такие как localForage, dexie.js, ZangoDB, PouchDB и JsStore, которые делают IndexedDB более удобным для программистов.

Быстро просмотрев все варианты, сравнив подходы к API, размеры пакетов, еженедельные загрузки на npm и содержание библиотек, я решил попробовать переписать свое доказательство концепции, используя Dexie.js. Описание Пер Декси:

Dexie.js - это библиотека-оболочка для IndexedDB - стандартной базы данных в браузере.

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

Вот как я подошел к решению проблемы сохранения данных в простом PWA, используя Dexie.js, React и одну из самых интересных будущих функций React, хуки.

Учебник

Первое, что следует отметить, это то, что вы захотите использовать окно в режиме инкогнито для всей разработки и тестирования на протяжении всего этого руководства. Если вы используете обычное окно, база данных не будет сброшена, пока вы не удалите ее вручную. Используя окно в режиме инкогнито, если вы ошиблись или хотите начать с чистого листа, вам просто нужно закрыть и снова открыть окно, чтобы все вернулось в нормальное состояние. Вы можете открыть окно в режиме инкогнито, щелкнув правой кнопкой мыши значок браузера и выбрав «Новое окно в режиме инкогнито [приватное]», или нажав Ctrl + Shift + n в Windows или ⌘ + Shift + n на Mac для Chrome.

Далее мы собираемся использовать create-react-app, чтобы упростить начало работы.

В вашем терминале введите:

npx create-react-app indexeddb-example && cd indexeddb-example

Теперь, когда мы закончили настройку нашего приложения React, давайте удалим все, что нам не нужно:

rm src/App.css src/App.test.js src/logo.svg

Большой! Теперь мы готовы начать писать. Во-первых, нам нужно зарегистрировать сервис-воркер, чтобы наше приложение работало в автономном режиме. Я не буду вдаваться в подробности о сервис-воркерах, но, к счастью, приложение create-react-app позволяет легко настроить простого сервис-воркера. Если вы хотите узнать больше об использовании сервис-воркеров с React, вот с чего я начал.

На данный момент все, что нам нужно знать, это то, что это позволит нам запускать приложение в автономном режиме. Важно отметить, что возможность автономного режима не будет доступна, пока мы не запустим npm run build, но мы до этого доберемся. В src/index.js в нижней части файла измените serviceWorker.unregister() на serviceWorker.register(). Ваш index.js теперь должен выглядеть так:

Хорошо, перейдем к src/App.js. Вы можете продолжить и удалить все в этом файле. Наш компонент приложения будет довольно простым. По сути, это будет просто div, содержащий компонент Form, с небольшой логикой для монтирования / размонтирования формы в демонстрационных целях.

Здесь происходит несколько вещей, но сначала нам нужно установить Dexie.js.

npm install dexie

App состоит из простого div с очень минимальным стилем, маленькой кнопки для открытия / закрытия (монтирования / размонтирования) формы и логики для фактического монтирования формы. Обратите внимание, мы также создаем соединение с базой данных всякий раз, когда монтируем форму. Если бы наш компонент приложения собирался часто перерисовывать, это не было бы хорошей идеей, и мы, вероятно, захотели бы переместить это в ловушку состояния, редукцию или что-то еще, но для наших целей это будет нормально. .

Теперь перейдем к сути этого урока. Давайте создадим в src файл с именем Form.js. Чтобы это сработало, нам нужно установить еще один пакет npm (обещаю, последний). Это позволит нам динамически скрывать нашу отправку, пока клиент не вернется в сеть.

npm install react-detect-offline

Вот Form.js

Комментарии должны быть в состоянии объяснить большую часть кода, но все, что мы на самом деле делаем, - это создаем управляемую форму с помощью React Hooks. Пока ничего особенного. Если вы запустите npm start, вы увидите, что эта форма «работает». Однако, если вы обновите страницу после ввода, данные исчезнут. Мы пока не сохраняем данные. Давайте воспользуемся той db опорой, которую мы передали. Во-первых, мы собираемся использовать другой хук, useEffect (не забудьте импортировать его из React вверху). Добавьте следующий код под вашим useState и над обработчиками событий:

Этот эффект будет вызываться только при изменении db prop, что в нашем случае происходит только при его монтировании. Мы устанавливаем это в строке 33, которая является вторым и необязательным аргументом useEffect. Первый аргумент, начинающийся в строке 4, - это функция, которая

  1. Подключается или создает магазин formData
  2. Выполняет транзакцию чтения / записи
  3. Получает значения для firstname и lastname или устанавливает их как пустые строки, если они еще не существуют
  4. Устанавливает значения из магазина как значения состояния
  5. Возвращает функцию, которая вызывается перед повторным запуском этого эффекта или при отключении компонента. Сама функция закрывает соединение с базой данных, поскольку оно нам больше не нужно после размонтирования формы.

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

К счастью, это не так уж сложно. Просто обновите setName, чтобы вызвать метод put в хранилище formData с идентификатором и новым значением:

Вот и все! Теперь вы можете ввести что-нибудь в форму, обновить страницу и убедиться, что ваши данные все еще там! Чтобы убедиться, что это работает, даже когда ваше приложение отключено, запустите npm run build, а затем serve -s build/. Возможно, вам сначала потребуется установить serve глобально, что можно сделать, запустив npm -g install serve. Обязательно откройте окно в режиме инкогнито / приватное, перейдите на localhost: 5000 и поиграйте с вводом своего имени, перейдя в автономный режим (что вы можете сделать на вкладке сети инспектора в Chrome) и обновите страницу.

Если что-то в вашем приложении работает неправильно, полный проект можно найти в этом репозитории GitHub.

Я надеюсь, что этот небольшой учебник будет полезен всем, кто хочет использовать API IndexedDB внутри приложения React. Если вам понравился этот урок, пожалуйста, похлопайте по нему или два. Если я что-то плохо объяснил или что-то не так с моим кодом, оставьте комментарий.