DEV Community

Nico Heinrich
Nico Heinrich

Posted on • Edited on

Svelte Stores x Dexie

Hey coding friends!

Today I solved a problem that had driven me mad yesterday. I wanted to connect the indexedDB with Svelte Stores to get what is often called "persistent stores" that last even when the browser window is closed. I have seen several tutorials on how to do this using Local Storage but only one using indexedDB (closingtags.com/svelte-stores-in-indexeddb). The latter might be totally fine, however, for me, as a beginner, it was kind of overwhelming.

Today I managed to come up with a very simple and reusable code that does exactly what I need — and I want to share it with you!

In order to use this, you need to install Dexie.js:

npm install dexie
Enter fullscreen mode Exit fullscreen mode

... and the following three files ...

db.js

This is the very minimalistic set-up for your indexedDB:

import Dexie from 'dexie';

export const db = new Dexie("user");

db.version(1).stores({
  user: "key, value"
});
Enter fullscreen mode Exit fullscreen mode

dbWriteble.js

This is a custom writable that handles loading data from the indexedDB on "init" and saving it on "set" (or automatically if you use the amazing $-syntax from Svelte). I got most of the code from this Video and simply added the init function and the indexedDB communication:

import { db } from "./db";
import { browser } from "$app/environment";

export function dbWritable(store, key, value) {
    let subscribeFunctions = [];

    async function init() {
        // checks if code runs in the browser and loads data from db
        if (browser) {
            const data = await db[store].get(key);
            // sets value of writable to data loaded
            if (data) set(data.value);
        }
    }

    function set(newValue) {
        value = newValue;

        subscribeFunctions.forEach(func => func(newValue));

        // saves value to db
        db[store].put({key, value});
    }

    function update(callback) {
        set(callback(value));
    }

    function subscribe(callback) {
        subscribeFunctions.push(callback);

        callback(value);

        return function() {
            subscribeFunctions = subscribeFunctions.filter(func => func !== callback);
        }
    }

    init();

    return {set, update, subscribe};
}
Enter fullscreen mode Exit fullscreen mode

stores.js

And this is your usual stores.js where you import the special dbWritable:

import { dbWritable } from "./dbWritable";

export let isDark = dbWritable("user", "isDark", false);
Enter fullscreen mode Exit fullscreen mode

Unlike usual writables, this dbWritable takes in three arguments: a store name, a key name and lastly a default value. Now this store can be used just like any normal Svelte store. However, when you close the browser and open it again, it is still there.

If you have any questions or improvements, let me know!

Cheers,

Nico

Top comments (0)