Svelte stores in localStorage – closingtags </>
Categories
Javascript Svelte

Svelte stores in localStorage

Svelte stores are great for managing state in an application but when combined with modern browser features. they really shine. Let’s take a look at how I implemented localStorage in a recent project with an annotated sample file:

$stores/local.js

import { browser } from '$app/environment';
import { writable } from 'svelte/store';
// it works with readable stores too!

// create an object w/default values
let goals = {
  goal1: 2000,
  goal2: 50
};

// ensure this only runs in the browser
if (browser) {
  // if the object already exists in localStorage, get it
  // otherwise, use our default values
  goals = JSON.parse(localStorage.getItem('goals')) || goals;
}

// export the store for usage elsewhere
export const goalStore = writable(goals);

if (browser) {
  // update localStorage values whenever the store values change
  goalStore.subscribe((value) =>
    // localStorage only allows strings
    // IndexedDB does allow for objects though... 🤔
    localStorage.setItem('goals', JSON.stringify(value))
  );
}

Throughout the rest of the app, the “goalStore” (and therefore, the localStorage object) can be accessed by importing in components like so:

<script>
    import { goalStore } from '$stores/local';
    import { browser } from '$app/environment';
</script>

<!-- prevent issues with SSR by only rendering dependent components in browser based environment -->
{#if browser}
    <!-- use '$' for reactivity and 'bind:' to keep data upstream in sync -->
    <Component bind:count={$goalStore.goal1} />
{/if}

As mentioned by Marc Rodney Tompkins in the comments, it may be necessary to wrap your code in browser checks as well. Svelte makes this easy with conditional {#if} blocks.

I hope this helps someone! If you’d like to see how I implemented this in its entirety, you can view the source code here.

By Dylan Hildenbrand

Dylan Hildenbrand smiling at the camera. I have tossled, brown hair, rounded glasses, a well-trimmed and short beard. I have light complexion and am wearing a dark sweater with a white t-shirt underneath.

Author and full stack web developer experienced with #PHP, #SvelteKit, #JS, #NodeJS, #Linux, #WordPress, and #Ansible. Check out my book at sveltekitbook.dev!

Do you like these posts? Consider sponsoring me on GitHub!

2 replies on “Svelte stores in localStorage”

This probably should have been obvious, but it took me a while to work out:
Not only do you need to browser-guard the workings of the store, but ALSO every reference in your .svelte files. This line:
will work when the page is first loaded (and for the life of me I don’t know why – it shouldn’t!) but if you refresh the page you will get
“TypeError: Cannot read properties of null (reading ‘goal1’)” on the server/in the dev console.
LocalStorage and SSR do _not_ mix. There may be some more sophisticated way around this, but I just wrapped my whole form in {#if browser} {/if} and it works now.

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.