A useful guide on how to use Stores and state management in Svelte
In this article, we gonna be talking about Stores and state management in Svelte.
As your application grows, you need to share data across the app. You will need to store data in a way that make it accessible to multiple component in your application. They also need to be reactive, so that any changes made to the data will be automatically shown in the components that are subscribed to the data source. That where store comes in.
Writable stores are a type of store in Svelte that allow you to create a mutable value that can be updated and read from multiple components. When a writable store is updated, all subscribed components will automatically re-render with the updated value.
Here's an example of creating and using a writable store in Svelte:
// store.js
import { writable } from 'svelte/store';
const count = writable(0);
You can now use count
in any of your Svelte component or even by regular JavaScript module. To use count in your Svelte component you can subscribe to it by calling the subscribe()
method on the store:
// counter.svelte
<script>
import { counter } from './store.js';
let count = 0;
counter.subscribe((value) => {
count = value;
});
</script>
<section>
<h1>{count}</h1>
</section>
To update the value in the store you can use update method which will invoke a callback in which the current value is passed as an argument:
function increment() {
counter.update((n) => n + 1);
}
function decrement() {
counter.update((n) => n - 1);
}
To change a value in the writable store, use the set
method. This method updates the store with a new value provided as an argument.
// reset counter
function reset() {
counter.set(0);
}
Svelte updates components using the observer pattern to keep up with changes to the data in a store. This means that when a component subscribes to a store, it starts watching the store. The component is alerted whenever the value of the store changes.
To avoid memory leaks, we need to unsubscribe from stores when you no longer need them. We can do this by calling the unsubscribe()
method on the store. It's best to do this in the onDestroy
life-cycle method of your Svelte component.
<script>
import { counter } from './store.js';
import { onDestroy } from 'svelte';
let count = 0;
let unsubscribe = counter.subscribe((value) => {
count = value;
});
function increment() {
counter.update((n) => n + 1);
}
function decrement() {
counter.update((n) => n - 1);
}
onDestroy(unsubscribe);
</script>
Svelte also has an automatic way of subscribing to a store using the $
symbol. Here's an example:
<script>
import { counter } from './store.js';
let count = 0;
$: count = $counter;
</script>
<section>
<h1>{count}</h1>
<button on:click={() => counter.update(n => n + 1)}>+</button>
<button on:click={() => counter.update(n => n - 1)}>-</button>
<button on:click={() => counter.set(0)}>reset</button>
</section>
In this example, we are using the $
symbol to subscribe to the counter
store. This means that the count
variable will always reflect the current value of counter
, and the component will automatically re-render whenever the value of counter
changes.
A readable store in Svelte creates a store whose value cannot be set from 'outside', which cannot be directly changed by a component. Instead, the value of a readable store comes from other stores or external data sources.
Here's an example of creating and using a readable store in Svelte:
// store.js
import { readable } from 'svelte/store';
const randomValue = readable(Math.random(), function start(set) {
const interval = setInterval(() => {
set(Math.random());
}, 1000);
return function stop() {
clearInterval(interval);
};
});
We can use randomValue
that generates a random number every second.
// random.svelte
<script>
import { randomValue } from './store.js';
</script>
<section>
<h1>{$randomValue}</h1>
</section>
Read-only stores are useful when you want to expose data to multiple components, but you don't want the value of the store to be changed by any of the components.
This function can help you make a store read-only. Even after making it read-only, you can still subscribe to changes from the original store using the new readable store.
import { readonly, writable } from 'svelte/store';
const writableStore = writable(1);
const readableStore = readonly(writableStore);
readableStore.subscribe(console.log);
writableStore.set(2); // console: 2
readableStore.set(2); // ERROR
Here's how to add a simple login authentication to a Svelte app:
Create a writable store called login
to track if a user is logged in or not. This store will hold a true or false value indicating the user's login status.
import { writable } from 'svelte/store';
export const login = writable(false);
To get started, make a LoginForm
tool that lets users type in their login info. When users submit their info, a function should check if their credentials are correct. If they are, the login
store should be set to true
.
<script>
import { login } from '../stores.js';
let username = '';
let password = '';
function authenticate() {
// Check credentials against backend API here
if (/* credentials are correct */) {
login.set(true);
}
}
</script>
<form on:submit|preventDefault="{authenticate}">
<label>
Username:
<input type="text" bind:value="{username}">
</label>
<label>
Password:
<input type="password" bind:value="{password}">
</label>
<button type="submit">Login</button>
</form>
In your app's main component, subscribe to the login
store and conditionally render either the LoginForm
component or the app's main content based on the user's login status.
<script>
import { login } from './stores.js';
import AuthenticatedContent from './AuthenticatedContent.svelte';
import UnAuthenticatedContent from './UnAuthenticatedContent.svelte';
</script>
{#if $login}
<AuthenticatedContent />
{:else}
<UnAuthenticatedContent />
{/if}
And that's it! We hope you found this article helpful in understanding how stores work in Svelte. By using stores, you can easily manage and share state across your application, making it more efficient and maintainable.
Join my web development newsletter to receive the latest updates, tips, and trends directly in your inbox.
Get ready for a daily dose of Svelte coding fun as we count down to Christmas. Join me on this festive coding journey and let's celebrate the holiday season together!
Slots, named slots, and slot props, the article also covers slots to create even more dynamic and flexible components in Svelte.
This article is all about using directives in Svelte. We'll go over how they work and how you can use them in your projects.