#svelte
#javascript
#frontend
Day 10: Stores & Universal Reactivity
Welcome to Day 10.
In Svelte 3/4, we had “Stores” (writable, readable). They were great.
In Svelte 5, we have Universal Reactivity.
Reactions Outside Components
You can use Runes ($state, $derived) in .svelte.ts (or .svelte.js) files! This basically obsoletes stores for 90% of use cases.
Creating a Store (counter.svelte.ts)
// counter.svelte.ts
let count = $state(0);
export function getCount() {
return count;
}
export function increment() {
count += 1;
}
Wait, count is a local variable in the module scope. It’s a singleton!
App.svelte
<script>
import { getCount, increment } from './counter.svelte.ts';
</script>
<button onclick={increment}>
Clicks: {getCount()}
</button>
Class-Based Stores
If you need multiple instances, use a class.
// ThemeManager.svelte.ts
export class ThemeManager {
isDark = $state(false);
toggle() {
this.isDark = !this.isDark;
}
}
export const theme = new ThemeManager(); // Singleton instance
Header.svelte
<script>
import { theme } from './ThemeManager.svelte.ts';
</script>
<button onclick={() => theme.toggle()}>
Mode: {theme.isDark ? 'Dark' : 'Light'}
</button>
Legacy Stores
The old writable stores still exist and are useful if you are integrating with RxJS or things that need the .subscribe pattern.
import { writable } from 'svelte/store';
export const count = writable(0);
But typically, just use $state in a shared file.
Challenge for Day 10
- Create
cart.svelte.ts. - It should hold an array of items (
$state([])). - Export functions
addItem(item)andtotal(a derived getter). - Use it in two different components (
ProductList.svelteandCartSummary.svelte) to prove they share state.
Solution:
// cart.svelte.ts
let items = $state([]);
export const cart = {
get items() { return items },
add(item) { items.push(item) },
get total() { return items.length }
};
You have mastered Svelte Core. Tomorrow, we graduate to SvelteKit – the meta-framework for building full apps.