Reading list Switch to dark mode

    How to use indexedDB (Dexie) in NextJs

    Updated 31 January 2024

    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.

    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.

    Start your headless eCommerce
    Find out More

    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.


    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


    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() {
          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 >
                <th>ROLL NUMBER </th>
                <th>DELETE   </th>
                <th>UPDATE  </th>
                studentList?.map((i: any, index: number) => {
                  return (
                    <tr key={index}>
                      <td style={{ paddingTop: '10px' }} ><span style={{ paddingLeft: '10px', paddingRight: '10px' }}>{}</span></td>
                      <td style={{ paddingTop: '10px' }} ><span style={{ paddingLeft: '10px', paddingRight: '10px' }}>{}</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(}>DELETE</button></td>
                      <td style={{ paddingTop: '10px' }} ><button onClick={() => setStudents({ ...i })} style={{ paddingLeft: '10px', paddingRight: '10px', marginLeft: '10px' }}>UPDATE</button></td>
      // Add and Update Form Component 
      return (
          <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: })} 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: })} 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>
            <h2 style={{ marginBottom: '20px', marginTop: '20px' }}>Student List</h2>
            <div><StudentList /></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";


    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 !!

    . . .

    Leave a Comment

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

    Be the first to comment.

    Back to Top

    Message Sent!

    If you have more details or questions, you can reply to the received confirmation email.

    Back to Home