Svelte Search

About

When to use `$state` vs stores?

In Svelte 5, the introduction of runes like $state has changed how we manage state. Let me explain when to use each approach and why:

When to use $state

Use $state for most reactive state management needs. It's simpler and more intuitive than stores because:

  1. It creates reactive variables that work like normal JavaScript variables
  2. No need to import anything or learn a new API
  3. Works with both primitive values and complex objects/arrays
  4. Automatically handles deep reactivity for nested objects/arrays

Example:

<script>
    // Simple counter with $state
    let count = $state(0);
</script>

<button on:click={() => count++}>
    Clicks: {count}
</button>

When to use stores

Stores are still useful in specific scenarios:

  1. Complex asynchronous data streams: If you're dealing with complex async operations or need fine-grained control over updates
  2. RxJS integration: If you want to reuse RxJS knowledge and patterns
  3. Legacy code: When maintaining Svelte 4 codebases
  4. Manual control: When you need explicit control over when and how values update

Example store usage:

<script>
    import { writable } from 'svelte/store';
    
    // Store-based counter
    const count = writable(0);
</script>

<button on:click={() => $count++}>
    Clicks: {$count}
</button>

Key Differences

Feature $state Stores
Syntax Simpler (just variables) More complex API
Reactivity Automatic Manual subscription
Deep reactivity Built-in Requires custom solutions
Async handling Basic More powerful
Cross-component Via props or context Via context or imports
Learning curve Lower Higher

Best Practices

  1. Default to $state: For most cases, start with $state as it's simpler and more intuitive
  2. Use stores when needed: Only reach for stores when you need their specific capabilities
  3. Shared state: For shared state across components, you can either:
    • Create a $state object in a separate file
    • Use context API with either approach
  4. Complex state: For deeply nested or complex state objects, $state's automatic deep reactivity is often better

Example of shared state with $state:

// state.svelte.js
export const userState = $state({
    name: 'John',
    preferences: {
        theme: 'dark',
        notifications: true
    }
});

Remember: The choice between $state and stores isn't always clear-cut. Start simple with $state, and only use stores when you encounter limitations or specific needs that $state can't handle well.