Dexie.js — Making IndexedDB Way Less Annoying

💬 Wait... What's This?
IndexedDB is a built-in browser feature that lets you store data locally, like for offline support. Sounds great, but it’s a headache to work with. It's full of boilerplate, callbacks, and weird transactions.
If you’re not familiar with IndexedDB or want a refresher, check out my full IndexedDB guide here. It’ll help you understand the basics before we jump into how Dexie.js can simplify it all.
Then I found Dexie.js, and it made everything easier. This post shows how Dexie works and why it's a great solution for managing IndexedDB with TypeScript and React.
🛠️ Installing Dexie
You can get Dexie in two ways:
If you’re using npm:
npm install dexie
npm install --save-dev @types/dexie
Or just drop it into your HTML with a CDN:
<script src="https://cdn.jsdelivr.net/npm/dexie@3.0.3/dist/dexie.js"></script>
📦 Making a Database (Without Losing Your Cool)
With Dexie, setting up a database is simple:
import Dexie from "dexie";
const db = new Dexie("MyDatabase");
db.version(1).stores({
friends: "++id,name,age"
});
new Dexie("MyDatabase")
: Names your database..version(1)
: Defines the version (you can update it later)..stores()
: Creates a "friends" store with fieldsid
,name
, andage
. The++id
means Dexie auto-increments theid
.
✍️ CRUD in Dexie (The Basics)
1. Add Stuff
db.friends.add({ name: "John Doe", age: 30 });
Done! John’s in the database.
2. Read Stuff
db.friends.get(1).then(friend => {
console.log(friend);
});
Gets the friend with ID 1.
3. Update Stuff
db.friends.update(1, { age: 31 }).then(updated => {
console.log(updated); // true if successful
});
John’s birthday update.
4. Delete Stuff
db.friends.delete(1);
And now... John’s gone. Sorry, John.
🔍 Searching (Without the Nonsense)
Want to find all friends older than 20?
db.friends.where("age").above(20).toArray().then(friends => {
console.log(friends);
});
It’s as simple as using Array.filter()
, but with Dexie handling the database.
🔄 Transactions (Do Multiple Things at Once)
You can group actions together:
db.transaction('rw', db.friends, () => {
db.friends.add({ name: "Alice", age: 25 });
db.friends.add({ name: "Bob", age: 22 });
}).catch(e => {
console.error("Something went wrong: ", e);
});
If one add fails, none of the actions are saved. It’s all-or-nothing.
🧯 Error Handling (Without Crying)
Dexie uses promises, so you can handle errors using .catch()
:
db.friends.add({ name: "Charlie", age: 26 }).catch(e => {
console.error("Oops:", e);
});
No cryptic IndexedDB errors — just regular JavaScript error handling.
🕵️ Fancy Stuff (Indexes and Filters)
Want to find all "John Doe"s?
db.friends.where("name").equals("John Doe").toArray().then(friends => {
console.log(friends);
});
Want to find all "John Doe"s over 20?
db.friends.where("age").above(20).and(friend => friend.name === "John Doe").toArray().then(friends => {
console.log(friends);
});
Dexie gives you power with simple, chainable methods.
You can find the full code for this Dexie.js tutorial on my GitHub here.
🧃 Final Thoughts
Dexie.js simplifies working with IndexedDB, making it much more manageable and less error-prone. With Dexie, you get the full power of IndexedDB without the headaches. If you’ve tried IndexedDB and found it too complicated, Dexie is definitely worth a try.
Subscribe to my newsletter
Read articles from Harshal directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
