React Hooks for Dexie.js

4.4.0 · active · verified Tue Apr 21

dexie-react-hooks provides a collection of React hooks designed for seamlessly integrating Dexie.js, a wrapper for IndexedDB, into React applications. It facilitates reactive data fetching and real-time updates directly from the IndexedDB database, abstracting away the complexities of manual subscription management. The current stable version is 4.4.0, aligning with the broader Dexie.js ecosystem releases. The package follows a release cadence tied closely to the main Dexie.js library, with frequent updates addressing bug fixes and new features, such as enhanced Y.js integration and Dexie Cloud capabilities. Its key differentiators include simplifying reactive state management with IndexedDB, offering idiomatic React patterns for database interactions, and ensuring components re-render automatically when underlying data changes.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates how to define a Dexie database, create a React component, and use `useLiveQuery` to fetch and display data reactively, with add and toggle functionality.

import React from 'react';
import { useLiveQuery } from 'dexie-react-hooks';
import Dexie from 'dexie';

// Define your Dexie database schema and class
interface Todo {
  id?: number;
  title: string;
  completed: boolean;
}

class MyDatabase extends Dexie {
  todos!: Dexie.Table<Todo, number>;

  constructor() {
    super('MyTodoDatabase');
    this.version(1).stores({
      todos: '++id, title, completed'
    });
  }
}

// Instantiate the database
const db = new MyDatabase();

// React component using the useLiveQuery hook
const TodoList: React.FC = () => {
  // useLiveQuery subscribes to changes in db.todos
  const todos = useLiveQuery(
    () => db.todos.toArray(),
    [] // Empty dependency array means the query function is stable; re-queries on DB changes.
  );

  const addTodo = async () => {
    await db.todos.add({ title: `New Todo ${Date.now()}`, completed: false });
  };

  const toggleTodo = async (id: number) => {
    const todo = await db.todos.get(id);
    if (todo) {
      await db.todos.update(id, { completed: !todo.completed });
    }
  };

  if (!todos) return <div>Loading todos...</div>; // Data is null on first render until query resolves

  return (
    <div>
      <h1>My Todos</h1>
      <button onClick={addTodo}>Add Todo</button>
      <ul>
        {todos.map(todo => (
          <li key={todo.id}>
            <input
              type="checkbox"
              checked={todo.completed}
              onChange={() => toggleTodo(todo.id!)}
            />
            <span style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>
              {todo.title}
            </span>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default TodoList;

view raw JSON →