Day 5: Using IndexedDB for Local Data Storage


Today, you’ll learn how to use IndexedDB for local data storage in your Progressive Web App (PWA). IndexedDB provides a way to store large amounts of structured data on the client-side, allowing your app to store and retrieve data even without a network connection.

What You Will Do Today:

  1. Understand IndexedDB and why it’s useful for PWAs.
  2. Set up IndexedDB using the idb library.
  3. Create, read, update, and delete data in IndexedDB.
  4. Use IndexedDB to cache data for offline access.

Step 1: Understanding IndexedDB

IndexedDB is a low-level API for storing significant amounts of structured data, including files and blobs. Unlike local storage, IndexedDB supports more complex queries, multiple data types, and large storage capacities. IndexedDB is especially useful in PWAs for caching data, such as API responses, for offline use.

Step 2: Setting Up IndexedDB with idb

The idb library provides a simpler way to interact with IndexedDB. Let’s install it and set up a database.

  1. Install idb:
   npm install idb
  1. Create a file named db.js in your src folder to set up the IndexedDB database:
   // src/db.js
   import { openDB } from 'idb';

   const DATABASE_NAME = 'MyPWA';
   const DATABASE_VERSION = 1;
   const STORE_NAME = 'items';

   export async function initDB() {
     return openDB(DATABASE_NAME, DATABASE_VERSION, {
       upgrade(db) {
         if (!db.objectStoreNames.contains(STORE_NAME)) {
           db.createObjectStore(STORE_NAME, { keyPath: 'id', autoIncrement: true });
         }
       },
     });
   }

   export async function addItem(item) {
     const db = await initDB();
     const tx = db.transaction(STORE_NAME, 'readwrite');
     await tx.store.add(item);
     await tx.done;
   }

   export async function getAllItems() {
     const db = await initDB();
     return db.getAll(STORE_NAME);
   }

   export async function deleteItem(id) {
     const db = await initDB();
     const tx = db.transaction(STORE_NAME, 'readwrite');
     await tx.store.delete(id);
     await tx.done;
   }

Explanation of Code:

  • initDB: Initializes the IndexedDB database. If the items object store doesn’t exist, it’s created with an auto-incrementing id.
  • addItem: Adds an item to the items store.
  • getAllItems: Retrieves all items from the items store.
  • deleteItem: Deletes an item by id.

Step 3: Adding and Retrieving Data from IndexedDB

Let’s create a component to add, retrieve, and display items stored in IndexedDB.

  1. Create a new file called Items.js in the src folder:
   // src/Items.js
   import React, { useState, useEffect } from 'react';
   import { addItem, getAllItems, deleteItem } from './db';

   function Items() {
     const [items, setItems] = useState([]);
     const [inputValue, setInputValue] = useState('');

     useEffect(() => {
       fetchItems();
     }, []);

     const fetchItems = async () => {
       const storedItems = await getAllItems();
       setItems(storedItems);
     };

     const handleAddItem = async () => {
       if (inputValue.trim()) {
         await addItem({ name: inputValue });
         setInputValue('');
         fetchItems();
       }
     };

     const handleDeleteItem = async (id) => {
       await deleteItem(id);
       fetchItems();
     };

     return (
       <div>
         <h2>Items</h2>
         <input
           type="text"
           value={inputValue}
           onChange={(e) => setInputValue(e.target.value)}
           placeholder="Add new item"
         />
         <button onClick={handleAddItem}>Add Item</button>

         <ul>
           {items.map((item) => (
             <li key={item.id}>
               {item.name} <button onClick={() => handleDeleteItem(item.id)}>Delete</button>
             </li>
           ))}
         </ul>
       </div>
     );
   }

   export default Items;

Explanation of Code:

  • fetchItems: Retrieves all items from IndexedDB and updates the component’s state.
  • handleAddItem: Adds a new item to IndexedDB and refreshes the list.
  • handleDeleteItem: Deletes an item from IndexedDB and refreshes the list.
See also  From Chaos to Cosmos: Building a Development Eden with Jenkins, Jira, Selenium, and Docker

Step 4: Integrating the Component into the App

  1. Open App.js and import the Items component to display it in the app:
   import React from 'react';
   import Items from './Items';

   function App() {
     return (
       <div>
         <h1>My PWA with IndexedDB</h1>
         <Items />
       </div>
     );
   }

   export default App;

Step 5: Testing IndexedDB for Offline Access

  1. Start the app using npm start.
  2. Add several items using the input box and the “Add Item” button.
  3. Open Developer Tools in your browser, go to Application > IndexedDB, and inspect the MyPWA database. You should see the items you added.
  4. Switch to offline mode in Developer Tools > Network > Offline and refresh the app. You should still see the items listed, as they are stored in IndexedDB.

Summary

Today, you used IndexedDB to store data locally in your PWA, allowing you to retrieve data even while offline. This feature adds robustness to your PWA by maintaining data availability regardless of network conditions.

Tomorrow, you’ll add push notifications to your PWA for user engagement.


Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.