Svelte Search

About

When to use `$state` vs stores?

I'm trying to understand the differences and when each is appropriate, especially with Svelte 5's new features.

Great question! Let's break this down clearly to understand when to use $state vs stores in Svelte 5.

Fundamental Concepts

  1. $state rune:

    • Introduced in Svelte 5
    • Creates reactive state that automatically updates the UI when changed
    • Simple to use - just declare with let variable = $state(initialValue)
    • Works with primitive values, arrays, and objects
    • Deeply reactive for objects/arrays (changes to nested properties are tracked)
  2. Stores (from svelte/store):

    • Existed since early Svelte versions
    • Provides more control over state updates
    • Requires explicit subscription to access values
    • Comes with different types: writable, readable, derived

When to Use Each

Use $state When:

  1. You want simple, straightforward reactive state
  2. Working with shared state that needs to be accessible across components
  3. You don't need complex async data handling
  4. You want the simplest syntax for reactivity

Example:

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

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

Use Stores When:

  1. You need complex async data streams (like RxJS observables)
  2. You want fine-grained control over updates
  3. You need to use Svelte's context API for state management
  4. Working with legacy code (pre-Svelte 5)

Example:

<script>
    import { writable } from 'svelte/store';
    
    const count = writable(0);  // Store-based state
    
    function increment() {
        count.update(n => n + 1);
    }
</script>

<button on:click={increment}>
    Clicks: {$count}
</button>

Key Differences

Feature $state Stores
Syntax Simpler More verbose
Reactivity Automatic, granular Requires explicit subscription
Async handling Less suited Better suited
Sharing across files Use .svelte.js file Use Context API
Legacy support Svelte 5+ only All versions

Best Practices in Svelte 5

  1. Shared State Across Components:
/// file: sharedState.svelte.js
export const appState = $state({
    count: 0,
    user: 'Guest'
});
  1. Component-Specific State:
<script>
    let localCount = $state(0);  // Local component state
</script>
  1. Complex Async Operations:
<script>
    import { writable } from 'svelte/store';
    
    const asyncData = writable(null);
    
    function fetchData() {
        // Complex async logic here
    }
</script>

Conclusion

In Svelte 5, prefer $state for most cases due to its simplicity and power. Use stores when you need:

  • Complex async data handling
  • Fine-grained control over updates
  • Legacy compatibility

Remember that $state and stores can coexist in the same project - use the right tool for each specific scenario.