Svelte stores

В SvelteKit stores представляют собой реактивный способ управления состоянием приложения, позволяя компонентам делиться данными без необходимости передавать их через пропсы. Stores обеспечивают централизованное хранение данных и автоматическое обновление компонентов при изменении состояния.

Svelte предлагает три основных типа встроенных stores: writable, readable и derived.


Writable Store

Writable store позволяет хранить изменяемое состояние, которое можно читать и обновлять. Создание такого store осуществляется через функцию writable из пакета svelte/store:

import { writable } from 'svelte/store';

export const count = writable(0);

Ключевые методы writable:

  • subscribe(callback) – подписка на изменения состояния. Возвращает функцию для отписки.
  • set(value) – устанавливает новое значение store.
  • upd ate(fn) – обновляет текущее значение с помощью функции, принимающей текущее значение и возвращающей новое.

Пример использования в компоненте:

<script>
  import { count } from './stores.js';

  function increment() {
    count.update(n => n + 1);
  }
</script>

<button on:click={increment}>
  Увеличить: {$count}
</button>

Здесь $count — это реактивный синтаксис Svelte для автоматической подписки на store. Любое изменение значения count автоматически обновит отображение.


Readable Store

Readable store предназначен для хранения данных, которые изменяются извне, например, при подписке на события или получение данных с сервера. Такой store предоставляет только подписку, без методов set и update для прямого изменения.

Создание readable store:

import { readable } from 'svelte/store';

export const time = readable(new Date(), function start(se t) {
  const interval = setInterval(() => {
    set(new Date());
  }, 1000);

  return () => clearInterval(interval); // функция очистки при отписке
});

Ключевые особенности:

  • set внутри функции start используется для обновления значения store.
  • Возвращаемая функция вызывается при отписке, позволяя очищать ресурсы.

Использование в компоненте:

<p>Текущее время: {$time.toLocaleTimeString()}</p>

Derived Store

Derived store создается на основе одного или нескольких существующих stores и вычисляет производное состояние. Это удобно для агрегирования или трансформации данных.

Пример:

import { derived } from 'svelte/store';
import { count } from './stores.js';

export const doubled = derived(count, $count => $count * 2);
  • Первый аргумент — исходный store или массив stores.
  • Второй аргумент — функция, вычисляющая новое значение на основе подписок.

В компоненте:

<p>Двойное значение: {$doubled}</p>

Любые изменения count автоматически пересчитают значение doubled.


Группировка и совместное использование данных

Stores удобны для глобального состояния, когда несколько компонентов должны реагировать на одни и те же данные. Можно создавать отдельный файл stores.js и экспортировать все stores:

import { writable, derived } from 'svelte/store';

export const user = writable({ name: 'Иван', loggedIn: false });
export const welcomeMessage = derived(user, $user => 
  $user.loggedIn ? `Привет, ${$user.name}!` : 'Добро пожаловать!'
);

Использование в разных компонентах:

<p>{$welcomeMessage}</p>

Авто-подписка и реактивность

Реактивный синтаксис $store позволяет автоматически подписываться и отписываться от store. Для более сложной логики можно использовать метод subscribe вручную:

import { count } from './stores.js';

const unsubscribe = count.subscribe(value => {
  console.log('Текущее значение:', value);
});

// Отписка при необходимости
unsubscribe();

Практические паттерны

  1. Модульный подход – каждый store в отдельном файле с логикой обновления.
  2. Композиция derived – создание вычисляемых состояний без дублирования данных.
  3. Подписка в onDestroy – при ручной подписке важно очищать ресурсы.
  4. Глобальные настройки – использование stores для тем, языков и пользовательских настроек.

Совместимость с SvelteKit

Stores отлично интегрируются с маршрутизацией SvelteKit, серверным рендерингом и асинхронными данными. Например, можно создавать store, который инициализируется данными с сервера:

import { writable } from 'svelte/store';

export const posts = writable([]);

export async function fetchPosts() {
  const res = await fetch('/api/posts');
  const data = await res.json();
  posts.set(data);
}

В компоненте:

<script>
  import { posts, fetchPosts } from './stores.js';
  fetchPosts();
</script>

{#each $posts as post}
  <p>{post.title}</p>
{/each}

Это позволяет хранить состояние независимо от компонентов, обеспечивая реактивность и согласованность данных по всему приложению.


Stores в SvelteKit представляют собой мощный инструмент для управления состоянием, позволяющий создавать реактивные и легко поддерживаемые приложения, минимизируя необходимость передачи данных через дерево компонентов и обеспечивая централизованное хранение логики состояния.