How to use indexedDB (Dexie) in NextJs
IndexedDB is a low-level API in web browsers that provides to store, retrieve, and perform transactions on large amounts of NoSQL data in the client’s browser.
It’s designed for web application development that needs to work offline or require large amounts of data to be stored locally.
Also, look no further and grab the opportunity to start your Magento 2 React development with the certified Magento 2 development company.
What is dexie?
Dexie is a JavaScript library that provides a higher-level API for working with IndexedDB.
It simplifies the process of interacting with IndexedDB by providing a more intuitive and developer-friendly interface.
Here are some key features of Dexie:
Promise-Based API:
Dexie uses Promises, which makes it easier to work with asynchronous operations.
Simplified Syntax:
It provides a clean and easy-to-use syntax for common operations like creating, reading, updating, and deleting data.
Querying and Filtering:
Dexie includes various methods with the help of these we can filter, and retrieve specific records.
Dexie Version Control:
This automatically updates the database and contributes to the schema version maintenance if we make any changes to our table.
Transactions:
Dexie abstracts transactions, making it easier to work with the IndexedDB transaction model.
Support for Complex Data Types:
Dexie can store more complex data types like arrays and objects.
Cross-Browser Compatibility:
It provides a consistent API across different browsers, handling any browser-specific quirks or inconsistencies.
Offline Support:
Dexie provides offline support which is useful for building progressive web apps ( PWA ) and with the help of Dexie we can store data locally and synchronize it with a server later.
Let’s see the implementation –
Step 1: Create a Next.js Project
The Next.js project must be finished and configured in the first stage for us to use the dexie library to conduct create, update, and delete operations.
To set up, we can follow this setup next js project blog that covers all about the setup.
Now our next app name is "next-dexie-implementation". The command below must be used to navigate the project directory after it has been established.
cd next-dexie-implementation
Step 2: Install Dependencies
We would install the necessary dependencies for working with dexie in our Next.js project. Execute the subsequent command within your terminal.
npm install dexie // dexie npm install dexie-react-hooks // dexie hook
Our project – structure look like as mentioned below
NEXT-DEXIE-IMPLEMENTATION/ │ ├── .next/ │ ├── components/ │ └── StudentMngmt.tsx │ ├── db/ │ └── db.model.ts │ ├── node_modules/ │ ├── pages/ │ ├── api/ │ │ └── hello.ts │ │ │ ├── _app.tsx │ ├── _document.tsx │ └── index.tsx │ ├── public/ │ ├── favicon.ico │ ├── next.svg │ └── vercel.svg │ ├── styles/ │ ├── globals.css │ └── Home.module.css │ ├── .eslintrc.json ├── .gitignore ├── next-env.d.ts ├── next.config.js ├── package-lock.json ├── package.json ├── README.md └── tsconfig.json
Step 3: DB model
Next, we’ll build the db.model.ts file and create a db subdirectory in the root directory.
import Dexie, { Table } from 'dexie';
// table inteface
export interface Student {
id?: number;
name: string;
rollNumber: number;
}
export class DB extends Dexie {
// table name is student
students!: Table<Student>;
constructor() {
super('myDatabase');
this.version(1).stores({
students: '++id, name, rollNumber'
});
}
}
export const db = new DB(); // export the db
students is our table name which name and rollNumber the key and primary key with id name
After initializing the students table we’ve exported it as DB below so that whenever we need to access this DB we can access it.
Step 4: Create, update, and delete operations with students table
As we earlier discussed make create, update, and delete operations with student table data and
there are three fields as you have seen in students that was name, rollNumber, and last is the primary key id.
To perform create, update, and delete operations we’ve created a components directory in the root folder under it we’ve created StudentMngmt.tsx and this file contains these code snippets.
import React, { FC } from "react";
import { db } from "@/db/db.model";
import { useLiveQuery } from "dexie-react-hooks";
const StudentMngmt: FC = () => {
const [students, setStudents] = React.useState({ name: '', rollNumber: '', id: null });
// dexie hook to get live data
const studentList = useLiveQuery(() => db.students.toArray());
// add student
const addStudent = React.useCallback(async () => {
if (students?.name && students?.rollNumber) {
await db.students.add({
name: students?.name,
rollNumber: Number(students?.rollNumber)
});
setStudents({ name: '', rollNumber: '', id: null });
}
}, [students])
// update student
const updateStudent = React.useCallback(async () => {
if (students?.id && students?.name && students?.rollNumber) {
await db.students.put({
id: students?.id,
name: students?.name,
rollNumber: Number(students?.rollNumber)
});
setStudents({ name: '', rollNumber: '', id: null });
}
}, [students])
// delete student
const deleteStudent = React.useCallback(async (id: any) => {
await db.students.delete(id);
}, [])
// Student list Component
const StudentList = () => {
return (
<div className="">
<table >
<tr>
<th>ID</th>
<th>NAME</th>
<th>ROLL NUMBER </th>
<th>DELETE </th>
<th>UPDATE </th>
</tr>
{
studentList?.map((i: any, index: number) => {
return (
<tr key={index}>
<td style={{ paddingTop: '10px' }} ><span style={{ paddingLeft: '10px', paddingRight: '10px' }}>{i.id}</span></td>
<td style={{ paddingTop: '10px' }} ><span style={{ paddingLeft: '10px', paddingRight: '10px' }}>{i.name}</span></td>
<td style={{ paddingTop: '10px' }} > <span style={{ paddingLeft: '10px', paddingRight: '10px' }}>{i.rollNumber}</span></td>
<td style={{ paddingTop: '10px' }} > <button onClick={addStudent} style={{ paddingLeft: '10px', paddingRight: '10px', marginLeft: '10px' }} onClickCapture={() => deleteStudent(i.id)}>DELETE</button></td>
<td style={{ paddingTop: '10px' }} ><button onClick={() => setStudents({ ...i })} style={{ paddingLeft: '10px', paddingRight: '10px', marginLeft: '10px' }}>UPDATE</button></td>
</tr>
)
})
}
</table>
</div>)
}
// Add and Update Form Component
return (
<div>
<div style={{ paddingLeft: '30px' }} >
<h2 style={{ marginBottom: '20px', marginTop: '20px' }}>{students?.id ? 'Update' : 'Add'} Student </h2>
<div >
<label htmlFor="Name" style={{ paddingRight: '10px' }}>Name</label>
<input type="text" value={students?.name} onChange={(e) => setStudents({ ...students, name: e.target.value })} placeholder="Name" name="Name" style={{ marginRight: '30px' }} />
<label htmlFor="roll" style={{ paddingRight: '10px' }}>Roll Number </label>
<input type="number" value={students?.rollNumber} onChange={(e) => setStudents({ ...students, rollNumber: e.target.value })} placeholder="Roll Number" name="rollNumber" />
{
students?.id ? (
<button onClick={updateStudent} style={{ paddingLeft: '10px', paddingRight: '10px', marginLeft: '10px' }}>SUBMIT</button>
) : (
<button onClick={addStudent} style={{ paddingLeft: '10px', paddingRight: '10px', marginLeft: '10px' }}>ADD</button>
)
}
</div>
<h2 style={{ marginBottom: '20px', marginTop: '20px' }}>Student List</h2>
<div><StudentList /></div>
</div>
</div>
);
}
export default StudentMngmt
Now let’s demystify StudentMngmt.tsx code snippet, here db is our indexdDB database exported from db.model.ts in which we’ve created students table after that we have also
import { db } from "@/db/db.model";
import { useLiveQuery } from "dexie-react-hooks";
useLiveQuery
Imported useLiveQuery that is a hook that provides live Query data from the table means
if you have added or updated the new data in students table or any table you don’t need to call the function or method again and again to get updated data.
const studentList = useLiveQuery(() => db.students.toArray());
Here studentList is student table data in array format which we’ve mapped in our StudentList component.
And in addStudent the function we’re using db.student.add({name:name , rollNumber:rollNumber})
likewise in updateStudent function, we’re using db.student.put({ id:id , name:name , rollNumber:rollNumber})
need to notice that this update Dexie API takes an extra key that is id, basically on the basis of it’ll find out the particular table data and update those data.
Now our last function related to Dexie operation is deleteStudent this Dexie API db.student.delete(id) just takes id to perform deletion.
Step 5: Importing into Route page :
At this moment we’re just at the curve toward finish so in our last step, import StudentMngmt.tsx the component into the route page here
we’ve imported it into index.tsx but it is your wish in which page you want to import. so the final result you can see below.
Conclusion: Integrating the Dexie library into a Next.js application provides a powerful client-side database solution.
Dexie simplifies the process of managing data on the client side, allowing for efficient storage and retrieval operations. By leveraging Dixie’s intuitive API and seamless
Integration with Next.js, developers can create dynamic and responsive web applications with robust offline capabilities.
Start your Headless Development with Webkul.
Happy Coding !!