{"id":16510,"library":"react-indexed-db","title":"React IndexedDB Hook","description":"react-indexed-db-hook provides a simplified interface for interacting with the browser's IndexedDB, exposed as a React Hook. It is a fork of `react-indexed-db` that primarily focuses on a hook-based API for modern React applications. The current stable version is 2.0.1. While it offers a context-based API, the maintainer explicitly states a lack of future support for it, pushing users towards the `useIndexedDB` hook. The library aims to abstract away the complexities of IndexedDB, providing common CRUD operations (getByID, getAll, add, update, delete) through a concise hook interface, making client-side data persistence more accessible in React projects. Its release cadence appears to be feature-driven rather than time-boxed, with updates addressing bugs or adding minor enhancements. Key differentiators include its explicit focus on a modern React hook API and a lightweight abstraction over raw IndexedDB.","status":"active","version":"2.0.1","language":"javascript","source_language":"en","source_url":"https://github.com/assuncaocharles/react-indexed-db","tags":["javascript","indexed","db","indexeddb","websql","sql","indexed-db","database","react","typescript"],"install":[{"cmd":"npm install react-indexed-db","lang":"bash","label":"npm"},{"cmd":"yarn add react-indexed-db","lang":"bash","label":"yarn"},{"cmd":"pnpm add react-indexed-db","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency required for all React components and hooks.","package":"react","optional":false}],"imports":[{"note":"Required to initialize the IndexedDB configuration globally before any hooks or context are used. Typically called once at the application's entry point.","wrong":"const { initDB } = require('react-indexed-db-hook');","symbol":"initDB","correct":"import { initDB } from 'react-indexed-db-hook';"},{"note":"The primary hook for interacting with a specific object store. It's a named export, not a default export. Pass the store name as an argument.","wrong":"import useIndexedDB from 'react-indexed-db-hook';","symbol":"useIndexedDB","correct":"import { useIndexedDB } from 'react-indexed-db-hook';"},{"note":"Although available, the maintainer does not plan on supporting the context API in the future. Prefer `initDB` and `useIndexedDB`.","wrong":"import IndexedDB from 'react-indexed-db-hook';","symbol":"IndexedDB (Context Provider)","correct":"import { IndexedDB } from 'react-indexed-db-hook';"},{"note":"Consumer for the `IndexedDB` context. Similar to `IndexedDB` provider, its use is discouraged due to lack of future support.","wrong":null,"symbol":"AccessDB (Context Consumer)","correct":"import { AccessDB } from 'react-indexed-db-hook';"}],"quickstart":{"code":"import React, { useEffect, useState } from 'react';\nimport { initDB, useIndexedDB } from 'react-indexed-db-hook';\n\n// 1. Define your DB configuration\nexport const DBConfig = {\n  name: 'MyTestDB',\n  version: 1,\n  objectStoresMeta: [\n    {\n      store: 'items',\n      storeConfig: { keyPath: 'id', autoIncrement: true },\n      storeSchema: [\n        { name: 'name', keypath: 'name', options: { unique: false } },\n        { name: 'value', keypath: 'value', options: { unique: false } }\n      ]\n    }\n  ]\n};\n\n// 2. Initialize the DB once at the application entry point\ninitDB(DBConfig);\n\ninterface Item {\n  id?: number;\n  name: string;\n  value: string;\n}\n\nconst ItemManager: React.FC = () => {\n  const { add, getAll, getByID, update, deleteRecord } = useIndexedDB<Item>('items');\n  const [items, setItems] = useState<Item[]>([]);\n  const [newItemName, setNewItemName] = useState('');\n  const [newItemValue, setNewItemValue] = useState('');\n  const [selectedItemId, setSelectedItemId] = useState<number | null>(null);\n  const [editItemName, setEditItemName] = useState('');\n  const [editItemValue, setEditItemNameValue] = useState('');\n\n  const refreshItems = async () => {\n    const allItems = await getAll();\n    setItems(allItems);\n  };\n\n  useEffect(() => {\n    refreshItems();\n  }, []);\n\n  const handleAddItem = async () => {\n    await add({ name: newItemName, value: newItemValue });\n    setNewItemName('');\n    setNewItemValue('');\n    refreshItems();\n  };\n\n  const handleEditSelect = async (id: number) => {\n    const item = await getByID(id);\n    if (item) {\n      setSelectedItemId(id);\n      setEditItemName(item.name);\n      setEditItemNameValue(item.value);\n    }\n  };\n\n  const handleUpdateItem = async () => {\n    if (selectedItemId) {\n      await update({ id: selectedItemId, name: editItemName, value: editItemValue });\n      setSelectedItemId(null);\n      setEditItemName('');\n      setEditItemNameValue('');\n      refreshItems();\n    }\n  };\n\n  const handleDeleteItem = async (id: number) => {\n    await deleteRecord(id);\n    refreshItems();\n  };\n\n  return (\n    <div>\n      <h1>Items</h1>\n      <div>\n        <input\n          type=\"text\"\n          placeholder=\"Name\"\n          value={newItemName}\n          onChange={(e) => setNewItemName(e.target.value)}\n        />\n        <input\n          type=\"text\"\n          placeholder=\"Value\"\n          value={newItemValue}\n          onChange={(e) => setNewItemValue(e.target.value)}\n        />\n        <button onClick={handleAddItem}>Add Item</button>\n      </div>\n\n      {selectedItemId && (\n        <div>\n          <h3>Edit Item (ID: {selectedItemId})</h3>\n          <input\n            type=\"text\"\n            value={editItemName}\n            onChange={(e) => setEditItemName(e.target.value)}\n          />\n          <input\n            type=\"text\"\n            value={editItemValue}\n            onChange={(e) => setEditItemNameValue(e.target.value)}\n          />\n          <button onClick={handleUpdateItem}>Update Item</button>\n          <button onClick={() => setSelectedItemId(null)}>Cancel</button>\n        </div>\n      )}\n\n      <ul>\n        {items.map((item) => (\n          <li key={item.id}>\n            {item.name}: {item.value}\n            <button onClick={() => handleEditSelect(item.id!)}>Edit</button>\n            <button onClick={() => handleDeleteItem(item.id!)}>Delete</button>\n          </li>\n        ))}\n      </ul>\n    </div>\n  );\n};\n\nexport default ItemManager;\n","lang":"typescript","description":"This quickstart demonstrates how to initialize the IndexedDB, use the `useIndexedDB` hook to perform CRUD operations (add, get, update, delete) on an 'items' object store, and display the items in a React component."},"warnings":[{"fix":"Migrate existing code to use the `initDB` function for initialization and the `useIndexedDB` hook for all database interactions. This aligns with the library's primary focus.","message":"The Context API (`<IndexedDB>` provider and `<AccessDB>` consumer) is not planned for future support by the maintainer. While it currently works, reliance on it may lead to issues with future updates or lack of bug fixes specific to the context API.","severity":"deprecated","affected_versions":">=2.0.0"},{"fix":"Place `initDB(DBConfig)` in your main application file (e.g., `App.tsx` or `index.tsx`) outside of any React component or in a top-level effect that runs once.","message":"It is crucial to call `initDB(DBConfig)` only once at the root level of your application, before any components that use `useIndexedDB` or `IndexedDB` context are mounted. Calling it multiple times or within a component's render cycle can lead to unexpected behavior or database initialization errors.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Verify your `DBConfig.objectStoresMeta` definitions. For `getByID`, `update`, `deleteRecord`, your data objects must consistently have the property defined by `keyPath` (e.g., `id`). When `autoIncrement` is false, make sure to explicitly provide the key in `add` operations.","message":"When defining `objectStoresMeta`, ensure that `keyPath` is correctly specified if you are relying on `getByID`, `update`, or `deleteRecord`. If `autoIncrement` is true, the database will handle key generation; otherwise, you must provide the key when adding records.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Ensure `initDB(DBConfig)` is called successfully at your application's entry point, before any components requiring IndexedDB access are rendered.","cause":"This usually indicates that `initDB` was not called or failed before attempting to use database operations via `useIndexedDB`.","error":"Uncaught (in promise) DOMException: The database is not running any transactions."},{"fix":"Double-check the method names from the `useIndexedDB` hook. The correct method for adding a record is `add` (not `addRecord` or `insert`). Ensure your TypeScript generic `useIndexedDB<T>` correctly reflects the type of objects in your store.","cause":"Incorrect method name or type inference issue. The library provides `add`, `getAll`, `getByID`, `update`, `deleteRecord`.","error":"Property 'add' does not exist on type '{ ... }'. Did you mean 'addRecord'?"},{"fix":"Verify that the string argument passed to `useIndexedDB` exactly matches the `store` property in one of your `objectStoresMeta` configurations in `DBConfig`.","cause":"The object store name provided to `useIndexedDB('storeName')` does not match any store defined in `DBConfig.objectStoresMeta`.","error":"Uncaught (in promise) DOMException: An object store with the specified name was not found or has been deleted."}],"ecosystem":"npm"}