Отредактировано 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, - это функция, которая
- Подключается или создает магазин
formData
- Выполняет транзакцию чтения / записи
- Получает значения для
firstname
иlastname
или устанавливает их как пустые строки, если они еще не существуют - Устанавливает значения из магазина как значения состояния
- Возвращает функцию, которая вызывается перед повторным запуском этого эффекта или при отключении компонента. Сама функция закрывает соединение с базой данных, поскольку оно нам больше не нужно после размонтирования формы.
Отлично, мы настроили нашу базу данных! Но мы все еще чего-то упускаем. Нам нужно, чтобы наши обработчики событий записывали в базу данных, когда происходит изменение, чтобы данные сохранялись, даже если мы перейдем в автономный режим и / или обновим страницу… также известную как постоянство.
К счастью, это не так уж сложно. Просто обновите setName
, чтобы вызвать метод put
в хранилище formData
с идентификатором и новым значением:
Вот и все! Теперь вы можете ввести что-нибудь в форму, обновить страницу и убедиться, что ваши данные все еще там! Чтобы убедиться, что это работает, даже когда ваше приложение отключено, запустите npm run build
, а затем serve -s build/
. Возможно, вам сначала потребуется установить serve
глобально, что можно сделать, запустив npm -g install serve
. Обязательно откройте окно в режиме инкогнито / приватное, перейдите на localhost: 5000 и поиграйте с вводом своего имени, перейдя в автономный режим (что вы можете сделать на вкладке сети инспектора в Chrome) и обновите страницу.
Если что-то в вашем приложении работает неправильно, полный проект можно найти в этом репозитории GitHub.
Я надеюсь, что этот небольшой учебник будет полезен всем, кто хочет использовать API IndexedDB внутри приложения React. Если вам понравился этот урок, пожалуйста, похлопайте по нему или два. Если я что-то плохо объяснил или что-то не так с моим кодом, оставьте комментарий.