Svelte Search

About

When to use `$state` vs stores?

In Svelte 5, the introduction of Runes, particularly the $state rune, has changed how we manage state in applications. Here's a detailed explanation of when to use $state vs stores, building on the context provided:


1. $state (Using Runes)

$state is the recommended approach for managing reactive state in Svelte 5. Here’s when and why to use it:

When to Use $state:

  • Simple Reactive State: When you need reactive variables that automatically update the UI when their values change.

    <script>
      let count = $state(0); // Reactive state
    </script>
    <button onclick={() => count++}>Clicks: {count}</button>
    

    Here, count is a reactive variable that triggers UI updates whenever it changes.

  • Shared State Across Components: Use $state to create shared state that can be imported and used in multiple components.

    // state.svelte.js
    export const userState = $state({
      name: 'John Doe',
    });
    
    <!-- App.svelte -->
    <script>
      import { userState } from './state.svelte.js';
    </script>
    <p>User name: {userState.name}</p>
    

    This makes userState accessible across multiple components without the need for stores.

  • Deep State Management: $state works seamlessly with arrays and objects, making them deeply reactive.

    let todos = $state([
      { done: false, text: 'Learn Svelte 5' }
    ]);
    

    Changes to todos or its nested properties will automatically trigger updates.

Why Use $state:

  • Simplicity: No need for additional APIs or boilerplate code. Just declare a variable with $state.
  • Universal Reactivity: Works both inside and outside components, making it ideal for shared state.
  • Performance: Optimized for granular updates, especially with deeply nested objects or arrays.

2. Stores (Legacy Approach)

Stores, from svelte/store, are still useful but are now considered a legacy solution in Svelte 5. Here’s when you might still use them:

When to Use Stores:

  • Complex Asynchronous Data Streams: If you're managing complex, asynchronous data (e.g., RxJS-style streams), stores provide better control over updates.
  • Manual Control Over Updates: Stores allow you to manually update values and listen to changes, which can be useful in specific scenarios.
  • Existing Codebase: If you're working with a Svelte 4 codebase or prefer the store API, you can continue using writable, readable, and derived stores.

Example of a Store:

<script>
  import { writable } from 'svelte/store';
  const count = writable(0); // Create a writable store
</script>
<button onclick={() => count.update(n => n + 1)}>Clicks: {$count}</button>

Why Use Stores (Legacy):

  • Fine-Grained Control: Stores allow manual updates and subscriptions.
  • Backward Compatibility: Useful for projects not yet migrated to Svelte 5.

Key Differences:

Feature $state (Runes) Stores (Legacy)
Ease of Use Simple and intuitive Requires boilerplate (writable, derived, etc.)
Reactivity Scope Universal (works anywhere) Limited to components or context
Performance Optimized for granular updates Slightly more overhead
Use Case General-purpose reactive state Complex async streams or legacy

When to Prefer $state Over Stores:

  1. New Projects: Always use $state for new Svelte 5 projects.
  2. Shared State: Use $state for shared state across components.
  3. Simple Reactivity: Use $state for straightforward reactive variables.

When to Prefer Stores Over $state:

  1. Legacy Code: When working with Svelte 4 or older codebases.
  2. Complex Async Logic: When you need fine-grained control over data streams.

Example Migrating from Stores to $state:

Legacy Store:

import { writable } from 'svelte/store';
export const count = writable(0);

$state Equivalent:

// state.svelte.js
export const count = $state(0);

Conclusion:

In Svelte 5, $state is the default and preferred way to manage reactive state due to its simplicity and universal reactivity. Stores are still available but should be reserved for specific use cases like complex async data streams or legacy code. Always favor $state for new development in Svelte 5!