Svelteのストアを使った効果的な状態管理方法とは?

Svelteは、他のJavaScriptフレームワークと比べて非常にシンプルで直感的なUI開発が可能なため、人気が高まっています。その中でも特に注目されているのが、Svelteのストアを使った状態管理です。状態管理は、アプリケーションの複雑さが増すにつれて重要性を増していく要素であり、データの一貫性やリアクティビティを確保するためには欠かせません。本記事では、Svelteのストアを利用して、効率的かつ効果的に状態管理を行うための方法について、基本から応用までを解説します。Svelte初心者でも理解しやすいように、コード例を交えながら説明していきますので、ぜひ参考にしてください。

目次

Svelteストアの基礎

Svelteのストアは、コンポーネント間でデータを共有し、リアクティブに状態を管理するための強力なツールです。Svelteのストアは、JavaScriptのオブジェクトや配列とは異なり、リアクティブにデータを扱えるように設計されています。これにより、データの変更が自動的にUIに反映されるため、手動でDOMを更新する必要がありません。

ストアの種類

Svelteには主に3種類のストアがあります。それぞれのストアは異なる目的で使用されます。

  1. Writableストア: 最も基本的なストアで、データの読み書きが可能です。任意のコンポーネントから値を設定し、変更することができます。
  2. Readableストア: 読み取り専用のストアで、外部からデータを更新することはできませんが、内部で定期的にデータを更新することができます。
  3. Derivedストア: 他のストアの値を基に計算された値を保持するストアです。これにより、複雑な状態の派生や計算を容易に行うことができます。

基本的な使い方

Svelteでストアを利用するには、svelte/storeモジュールから必要なストアをインポートします。以下は、Writableストアの基本的な例です。

import { writable } from 'svelte/store';

const count = writable(0);  // 初期値を0に設定したWritableストア

// 値を更新
count.set(1);

// 現在の値に対して加算
count.update(n => n + 1);

// ストアを購読して、値が変更されるたびに処理を実行
count.subscribe(value => {
    console.log(value);  // 値が変更されると、コンソールに出力されます
});

この例では、writable関数を使ってカウントを管理するストアを作成しています。ストアの値は、setupdateメソッドを使って変更でき、変更が発生するとストアを購読しているすべてのコンポーネントが自動的に再レンダリングされます。

Svelteのストアを理解することで、コンポーネント間でのデータ共有やリアクティブなUIの実装がスムーズになります。次のセクションでは、リアクティブな状態管理についてさらに詳しく見ていきましょう。

リアクティブな状態管理とは?

Svelteの最も強力な特徴の一つが、リアクティブなデータバインディングです。これは、データの変化に応じて自動的にUIが更新される仕組みを指します。リアクティブな状態管理を使用することで、アプリケーションの状態を直感的に扱うことができ、開発の効率が大幅に向上します。

Svelteにおけるリアクティブ性

Svelteでは、通常のJavaScript変数に対してもリアクティブな挙動を持たせることができます。これは、変数が変更されると、それに依存するすべての部分が自動的に再評価されるという仕組みです。Svelteではこの機能を利用して、コードをシンプルに保ちながらも、複雑なUIをリアクティブに管理することができます。

例として、以下のようなコードを考えてみましょう。

<script>
    let count = 0;

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

<button on:click={increment}>
    カウント: {count}
</button>

この例では、countという変数がボタンのテキストにバインディングされています。ボタンをクリックすると、countが増加し、それに応じてボタンに表示されるテキストも自動的に更新されます。このように、Svelteでは変数の変更が直ちにUIに反映されるため、余計なコードを書く必要がありません。

Svelteストアのリアクティブ性

ストアを利用すると、さらに強力なリアクティブ性を活用できます。ストアの値が変更されると、その値に依存するすべてのコンポーネントが再レンダリングされます。以下に、Writableストアを使ったリアクティブな状態管理の例を示します。

<script>
    import { writable } from 'svelte/store';

    const count = writable(0);

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

<button on:click={increment}>
    カウント: {$count}
</button>

この例では、countストアの値がボタンのテキストにバインディングされています。$countという記法を使うことで、ストアの値をリアクティブに取り出し、UIにバインディングすることができます。これにより、ストアの値が変更されるたびに、UIが自動的に更新されます。

リアクティブな状態管理を理解することで、Svelteでの開発が一層簡単かつ効果的になります。次のセクションでは、具体的にWritableストアを使った実装方法について詳しく解説していきます。

Writableストアの実装

Writableストアは、Svelteで最も基本的なストアタイプで、データの読み書きが可能です。これにより、アプリケーション内で状態を簡単に管理し、必要に応じてその状態を更新することができます。ここでは、Writableストアの基本的な実装例を紹介し、その使用方法を詳しく説明します。

Writableストアの作成

Writableストアを作成するには、svelte/storeモジュールからwritable関数をインポートします。writable関数に初期値を渡すことで、ストアが作成されます。以下の例では、カウントを管理するシンプルなストアを作成しています。

import { writable } from 'svelte/store';

export const count = writable(0);

このコードは、countという名前のストアを作成し、初期値を0に設定しています。このストアは、Svelteのどのコンポーネントでもインポートして使用することができます。

ストアの購読と更新

Writableストアは、他のコンポーネントから値を読み取ったり、更新したりすることができます。ストアの値にアクセスするには、$記号を使います。また、ストアの値を更新するためにsetupdateメソッドを使用します。

以下は、countストアを利用したカウントアップの例です。

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

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

<button on:click={increment}>
    カウント: {$count}
</button>

この例では、countストアがインポートされ、その値がボタンにバインディングされています。increment関数では、updateメソッドを使ってcountの値を1増やしています。ボタンをクリックするたびに、ストアの値が増加し、それに伴ってボタンに表示されるカウントがリアクティブに更新されます。

複数コンポーネントでのストアの共有

Writableストアの利点の一つは、アプリケーション全体で状態を簡単に共有できることです。複数のコンポーネントで同じストアを購読することで、状態を一貫して管理することができます。

たとえば、次のように複数のコンポーネントが同じcountストアを使用している場合、いずれかのコンポーネントでストアが更新されると、他のコンポーネントも自動的に再レンダリングされます。

<!-- CounterButton.svelte -->
<script>
    import { count } from './store.js';

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

<button on:click={increment}>
    カウント: {$count}
</button>
<!-- DisplayCount.svelte -->
<script>
    import { count } from './store.js';
</script>

<p>現在のカウント: {$count}</p>

これらのコンポーネントを同じページで使用すると、ボタンをクリックするたびに表示されるカウントが両方のコンポーネントでリアクティブに更新されます。

Writableストアを使うことで、アプリケーションの状態管理がより直感的でシンプルになります。次のセクションでは、読み取り専用のReadableストアの使い方について解説します。

Readableストアの利用方法

Readableストアは、Svelteで提供される読み取り専用のストアで、外部から値を変更することができないタイプのストアです。これにより、一定の値が一貫して保持される場面で役立ちます。Readableストアは、タイマーや日時など、定期的に変化するデータを扱う際に特に有効です。

Readableストアの作成

Readableストアを作成するには、svelte/storeモジュールからreadable関数をインポートします。readable関数には、初期値と、値の変更を制御するための関数を渡します。この関数内で、値を更新するロジックを定義することができます。

以下は、現在の日時を保持するReadableストアの例です。

import { readable } from 'svelte/store';

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

    return function stop() {
        clearInterval(interval);
    };
});

このコードでは、timeというReadableストアを作成し、初期値として現在の日時を設定しています。ストアは1秒ごとに更新され、set関数を使って新しい日時をストアに設定します。また、stop関数はストアが不要になったときにインターバルをクリアします。

Readableストアの購読

Readableストアは他のストアと同様に購読することができます。購読することで、ストアの値が変更されるたびにUIが自動的に更新されます。

次の例は、先ほど作成したtimeストアを使って、現在の時刻を表示するコンポーネントです。

<script>
    import { time } from './store.js';
</script>

<p>現在の時刻: {$time}</p>

このコンポーネントは、timeストアを購読し、現在の時刻をリアクティブに表示します。$timeと記述することで、ストアの最新の値を自動的に取得し、表示することができます。毎秒、時刻が更新されるたびに、このコンポーネントの表示も自動的に更新されます。

Readableストアの活用例

Readableストアは、リアルタイムデータや定期的に更新される情報を扱う際に非常に便利です。以下に、Readableストアを使ったいくつかのユースケースを示します。

  1. タイマーやストップウォッチ: ストップウォッチやカウントダウンタイマーを作成し、時間の経過をリアルタイムで表示する際に使用できます。
  2. センサーやAPIからのデータ取得: センサーからのデータや、外部APIから定期的に取得するデータを扱う場合に、Readableストアを利用してデータを保持し、更新します。
  3. ロケーションデータの追跡: ユーザーの現在位置を追跡し、地図上に表示するアプリケーションで、Readableストアを使って位置情報を更新できます。

Readableストアは、一貫した読み取り専用のデータソースを必要とする場合に役立ちます。次のセクションでは、複数のストアから派生したデータを管理するためのDerivedストアについて解説します。

Derivedストアでの派生データ管理

Derivedストアは、他のストアの値を基にして新しい値を計算・生成するためのストアです。これにより、複数のストアの値を組み合わせたり、特定の条件に基づいて派生データを管理することができます。Derivedストアは、Svelteの状態管理において非常に強力で、コードの複雑さを軽減しつつ、動的なデータ処理を可能にします。

Derivedストアの作成

Derivedストアを作成するには、svelte/storeモジュールからderived関数をインポートします。derived関数には、元となるストアと、それに基づいて計算を行う関数を渡します。この関数は、元のストアの値が変更されるたびに再評価され、Derivedストアの値が更新されます。

以下は、countmultiplierという二つのストアを使って、新しいresultというDerivedストアを作成する例です。

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

export const count = writable(2);
export const multiplier = writable(3);

export const result = derived(
    [count, multiplier],
    ([$count, $multiplier]) => $count * $multiplier
);

この例では、countmultiplierの値を掛け合わせた結果をresultとして保持するDerivedストアを作成しています。derived関数に渡された配列のストアが更新されるたびに、resultの値も自動的に更新されます。

Derivedストアの利用方法

Derivedストアも通常のストアと同じように購読したり、バインディングしたりすることができます。次の例では、先ほど作成したresultストアを使って計算結果を表示するコンポーネントを示します。

<script>
    import { count, multiplier, result } from './store.js';
</script>

<p>カウント: {$count}</p>
<p>乗数: {$multiplier}</p>
<p>結果: {$result}</p>

このコンポーネントでは、countmultiplier、およびresultの各ストアをバインディングして、値を表示しています。countmultiplierの値が変更されると、それに応じてresultの値も自動的に更新され、結果がリアルタイムで表示されます。

Derivedストアの活用例

Derivedストアは、特定の条件や複数のデータソースに基づいた動的なデータ管理に非常に有効です。以下にDerivedストアを使ったいくつかのユースケースを示します。

  1. フィルタリングとソート: リストのフィルタリングやソートにDerivedストアを使用することで、元のデータセットに影響を与えずに、派生した表示用のデータを作成できます。
  2. 複雑な計算の管理: 元のストアの値に基づいて複雑な計算を行い、その結果をDerivedストアとして管理することができます。例えば、フォームの入力に基づいて動的に計算される合計値やパーセンテージなどが考えられます。
  3. 状態の合成: 複数のストアからの値を合成し、新しい状態を生成する場合に、Derivedストアを利用することで、コードをシンプルに保ちつつ、柔軟な状態管理を実現できます。

Derivedストアを使用することで、複数のデータ源から動的に派生したデータを効率的に管理することが可能になります。次のセクションでは、Svelteストアの実際の応用例を紹介し、さらに理解を深めていきます。

Svelteストアの応用例

Svelteストアを使った状態管理は、シンプルなデータの保持だけでなく、複雑なアプリケーションにおいても非常に有用です。ここでは、Svelteストアのいくつかの実際の応用例を紹介し、ストアがどのようにして様々な状況で活用できるかを解説します。

フォームの状態管理

フォームのデータを管理する際、Svelteストアを使うことで、複数の入力フィールドの状態を効率的に保持し、管理することができます。例えば、ユーザー登録フォームの状態をストアで管理し、リアルタイムにバリデーションを行うケースを考えてみます。

import { writable } from 'svelte/store';

export const username = writable('');
export const email = writable('');
export const password = writable('');

export const isFormValid = derived(
    [username, email, password],
    ([$username, $email, $password]) => {
        return $username.length > 0 && $email.includes('@') && $password.length >= 8;
    }
);

この例では、usernameemailpasswordの各ストアに入力された値を保持し、それらを基にフォームが有効かどうかを判定するisFormValidというDerivedストアを作成しています。これにより、ユーザーが入力するたびにバリデーションがリアルタイムで行われ、フォームの有効性がチェックされます。

ダッシュボードのデータフィルタリング

ダッシュボードアプリケーションでは、データのフィルタリングがよく行われます。Svelteストアを使用して、選択されたフィルタに基づいて表示されるデータを管理することができます。

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

export const selectedCategory = writable('all');
export const allItems = writable([
    { id: 1, category: 'books', name: 'Svelte Handbook' },
    { id: 2, category: 'electronics', name: 'Laptop' },
    { id: 3, category: 'books', name: 'JavaScript Guide' },
    { id: 4, category: 'electronics', name: 'Smartphone' },
]);

export const filteredItems = derived(
    [selectedCategory, allItems],
    ([$selectedCategory, $allItems]) => {
        return $selectedCategory === 'all'
            ? $allItems
            : $allItems.filter(item => item.category === $selectedCategory);
    }
);

ここでは、全てのアイテムを保持するallItemsストアと、選択されたカテゴリーを保持するselectedCategoryストアを使用しています。filteredItemsというDerivedストアでは、選択されたカテゴリーに基づいて表示すべきアイテムを動的にフィルタリングしています。これにより、ユーザーがカテゴリーを変更するたびに表示されるアイテムリストがリアルタイムで更新されます。

グローバルなアプリケーション設定の管理

アプリケーション全体に影響を与える設定(例: ダークモードの切り替え、言語設定など)をSvelteストアで管理することで、設定の変更がアプリ全体に即座に反映されます。

import { writable } from 'svelte/store';

export const isDarkMode = writable(false);

function toggleDarkMode() {
    isDarkMode.update(value => !value);
}

このコードでは、isDarkModeというストアを作成し、ダークモードの状態を保持しています。toggleDarkMode関数を呼び出すことで、ダークモードのオン・オフを切り替え、アプリケーション全体のスタイルを動的に変更することができます。

Svelteストアは、これらの応用例を通じて、シンプルな状態管理から複雑な状態管理まで柔軟に対応できることが分かります。次のセクションでは、効率的な状態管理を行うためのベストプラクティスについて解説します。

ストアを使った状態管理のベストプラクティス

Svelteのストアを使って効果的に状態管理を行うには、いくつかのベストプラクティスを押さえておくことが重要です。これらのベストプラクティスを理解し、適切に適用することで、アプリケーションの可読性や保守性が大幅に向上し、バグの発生を減らすことができます。

状態の最小化

状態管理における基本的な原則として、「状態は必要最小限に保つ」ことが挙げられます。無駄に多くの状態を管理しようとすると、複雑さが増し、予期しない動作が発生する可能性が高まります。可能な限り、状態はDerivedストアや関数で計算できるようにし、最小限の状態だけをWritableストアで管理するようにしましょう。

不要な状態を持たない例

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

export const items = writable([...]); // アイテムのリスト

// フィルタリングされたアイテムは計算によって生成
export const filteredItems = derived(items, $items =>
    $items.filter(item => item.isActive)
);

この例では、filteredItemsの状態を計算によって生成することで、直接管理する状態の量を減らしています。

コンポーネント間のデータ共有を意識する

アプリケーションが大きくなると、コンポーネント間でデータを共有する必要が出てきます。グローバルな状態が必要な場合には、できるだけストアを使ってデータを管理し、プロパティの過剰なバケツリレーを避けるようにしましょう。これにより、データの流れがシンプルになり、コードが見やすくなります。

グローバルな状態の管理例

// store.js
import { writable } from 'svelte/store';

export const authStatus = writable(false);
<!-- Navbar.svelte -->
<script>
    import { authStatus } from './store.js';
</script>

<nav>
    {#if $authStatus}
        <button>ログアウト</button>
    {:else}
        <button>ログイン</button>
    {/if}
</nav>

この例では、authStatusがグローバルに管理され、複数のコンポーネント間で状態を簡単に共有できるようになっています。

Derivedストアを活用する

Derivedストアを活用することで、計算された値や派生データを簡単に管理できます。複数の状態を組み合わせたり、特定の条件に基づいてデータをフィルタリングしたりする場合には、Derivedストアを利用することで、コードの見通しが良くなり、バグを減らすことができます。

派生データの例

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

export const count = writable(10);
export const doubleCount = derived(count, $count => $count * 2);

この例では、countから計算されたdoubleCountが自動的に管理され、状態管理が簡素化されています。

コンポーネントの分割と再利用性

状態管理を行う際には、コンポーネントの再利用性を意識しましょう。特定の機能に依存しすぎず、汎用性の高いコンポーネントを作成することで、コードの再利用が促進され、メンテナンスが容易になります。

再利用可能なコンポーネントの例

<!-- Counter.svelte -->
<script>
    export let count;
</script>

<button on:click={() => count.update(n => n + 1)}>
    カウント: {$count}
</button>

このCounterコンポーネントは、任意のcountストアを渡すことで再利用可能な設計になっています。

ストアの破棄とクリーンアップ

ストアが不要になった際には、必ず適切にクリーンアップを行いましょう。特に、外部APIとの通信やタイマーを使用する場合には、メモリリークや不要なリソース消費を防ぐために、クリーンアップが重要です。

クリーンアップの例

import { readable } from 'svelte/store';

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

    return function stop() {
        clearInterval(interval);
    };
});

この例では、ストアが破棄された際にインターバルがクリアされるようになっています。

これらのベストプラクティスを守ることで、Svelteのストアを使った状態管理がさらに効果的かつ効率的になります。次のセクションでは、他の状態管理ライブラリとの比較を行い、Svelteストアの利点を強調します。

他の状態管理ライブラリとの比較

Svelteのストアは、そのシンプルさと強力なリアクティブ機能で知られていますが、他の人気のある状態管理ライブラリ、例えばReduxやVuexとはどのように異なるのでしょうか?ここでは、Svelteストアを他の状態管理ライブラリと比較し、それぞれの特徴や利点を明らかにします。

Reduxとの比較

Reduxは、Reactエコシステムで広く使用されている状態管理ライブラリです。単一の大規模なグローバルストアを持ち、アクションとリデューサーを使って状態を変更するという特徴があります。これは、アプリケーション全体の状態が一元管理されるというメリットがありますが、複雑なアプリケーションでは大量のボイラープレートコードが必要になるというデメリットもあります。

一方、Svelteのストアは、コンポーネントごとにローカルな状態を持つことができ、必要に応じてグローバルな状態も簡単に共有できます。さらに、Svelteではアクションやリデューサーのような抽象化が不要で、状態の変更が直接的かつ簡単に行えます。これにより、コードがよりシンプルで明瞭になります。

比較ポイント

  • シンプルさ: SvelteのストアはReduxよりもはるかにシンプルで、初学者にも扱いやすい。
  • ボイラープレート: Reduxでは多くの設定やコードが必要だが、Svelteでは必要最低限のコードで状態管理が可能。
  • 適用範囲: Reduxは大規模なアプリケーションに向いているが、Svelteは小〜中規模のアプリケーションに最適。

Vuexとの比較

Vuexは、Vue.jsアプリケーションのための公式状態管理ライブラリで、Vueコンポーネント間で状態を共有するために使用されます。Vuexは、ストア、ゲッター、ミューテーション、アクションという構成を持ち、状態の管理を厳密に行うことができます。しかし、これもまた、設定が複雑になる可能性があり、特に小規模なアプリケーションでは過剰に感じることがあります。

Svelteストアは、Vuexに比べて軽量で、設定も非常にシンプルです。ミューテーションやアクションを定義する必要がなく、直接ストアの値を更新することができるため、直感的で扱いやすいのが特徴です。また、Svelteのリアクティブなデータバインディング機能により、ストアの変更が即座にUIに反映されるため、開発がスムーズになります。

比較ポイント

  • 構造のシンプルさ: Vuexは構造が複雑だが、Svelteのストアはシンプルで理解しやすい。
  • 設定の手軽さ: SvelteのストアはVuexに比べて設定が少なく、すぐに使い始めることができる。
  • リアクティビティ: Svelteのリアクティブシステムは強力で、ストアの変更が即座にUIに反映される。

その他のライブラリとの比較

その他の状態管理ライブラリ(例えばMobXやRecoilなど)とも比較すると、Svelteのストアは以下の点で優れています。

  1. 学習曲線: Svelteのストアは学習が容易で、他のライブラリに比べて学習曲線が緩やかです。Svelteの基本的な知識があれば、すぐに使い始めることができます。
  2. パフォーマンス: Svelteはコンパイル時に不要なコードを排除するため、他のライブラリよりも軽量で、パフォーマンスに優れています。ストアもその恩恵を受けており、特にモバイルデバイスやリソースが限られた環境で効果的です。
  3. 統合性: Svelteのストアはフレームワークに統合されているため、追加のライブラリをインストールする必要がなく、プロジェクトの依存関係が少なくなります。

まとめ

Svelteのストアは、他の状態管理ライブラリと比較してシンプルで扱いやすく、特に小〜中規模のアプリケーションに最適です。ReduxやVuexが必要とするような複雑な設定やボイラープレートコードが不要で、直感的に状態を管理することができます。また、Svelteのリアクティブなデータバインディング機能と相まって、UIの更新がスムーズかつ効率的に行えるのが大きな強みです。次のセクションでは、Svelteストアを使った状態管理を深く理解するための演習問題を紹介します。

演習問題

ここでは、Svelteストアを使った状態管理の理解を深めるための演習問題を紹介します。これらの問題に取り組むことで、ストアの基本的な使い方から、複数のストアを組み合わせた高度な状態管理までを実践的に学ぶことができます。

演習1: シンプルなカウンター

目標: Writableストアを使って、カウントアップとカウントダウンができるシンプルなカウンターを作成します。

手順:

  1. countという名前のWritableストアを作成し、初期値を0に設定します。
  2. + ボタンをクリックするとカウントアップし、- ボタンをクリックするとカウントダウンするようにしてください。
  3. 現在のカウント値を表示します。

期待される結果:

  • ボタンをクリックするたびに、表示されるカウント値が変更されます。
<script>
    import { writable } from 'svelte/store';

    const count = writable(0);

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

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

<button on:click={decrement}>-</button>
<span>{$count}</span>
<button on:click={increment}>+</button>

演習2: 動的なテーマ切り替え

目標: Readableストアを使って、アプリケーション全体のテーマ(ライトモード/ダークモード)を動的に切り替えます。

手順:

  1. isDarkModeという名前のWritableストアを作成し、初期値をfalseに設定します。
  2. ボタンをクリックすることで、isDarkModeの値を切り替え、ライトモードとダークモードを変更できるようにします。
  3. 現在のテーマに応じて、背景色とテキスト色が変更されるようにCSSを適用します。

期待される結果:

  • ボタンをクリックすると、テーマがライトモードとダークモードの間で切り替わります。
<script>
    import { writable } from 'svelte/store';

    const isDarkMode = writable(false);

    function toggleTheme() {
        isDarkMode.update(value => !value);
    }
</script>

<button on:click={toggleTheme}>
    {$isDarkMode ? 'ライトモードに切り替え' : 'ダークモードに切り替え'}
</button>

<style>
    body {
        background-color: {$isDarkMode ? '#333' : '#fff'};
        color: {$isDarkMode ? '#fff' : '#000'};
    }
</style>

演習3: フィルタリングされたアイテムリスト

目標: Derivedストアを使って、カテゴリに基づいてアイテムリストをフィルタリングします。

手順:

  1. itemsという名前のWritableストアを作成し、複数のアイテム(例: 名前とカテゴリ)を含むリストを保持します。
  2. selectedCategoryというWritableストアを作成し、選択されたカテゴリを管理します。
  3. filteredItemsというDerivedストアを作成し、選択されたカテゴリに基づいてアイテムリストをフィルタリングします。
  4. フィルタリングされたアイテムリストを画面に表示します。

期待される結果:

  • カテゴリを選択すると、そのカテゴリに属するアイテムのみがリストに表示されます。
<script>
    import { writable, derived } from 'svelte/store';

    const items = writable([
        { id: 1, name: 'Apple', category: 'Fruit' },
        { id: 2, name: 'Carrot', category: 'Vegetable' },
        { id: 3, name: 'Banana', category: 'Fruit' },
        { id: 4, name: 'Broccoli', category: 'Vegetable' }
    ]);

    const selectedCategory = writable('All');

    const filteredItems = derived(
        [items, selectedCategory],
        ([$items, $selectedCategory]) => {
            return $selectedCategory === 'All'
                ? $items
                : $items.filter(item => item.category === $selectedCategory);
        }
    );

    function selectCategory(category) {
        selectedCategory.set(category);
    }
</script>

<select on:change="{e => selectCategory(e.target.value)}">
    <option value="All">All</option>
    <option value="Fruit">Fruit</option>
    <option value="Vegetable">Vegetable</option>
</select>

<ul>
    {#each $filteredItems as item}
        <li>{item.name}</li>
    {/each}
</ul>

演習4: リアルタイム検索機能

目標: 検索クエリに基づいて、リストのアイテムをリアルタイムでフィルタリングします。

手順:

  1. searchQueryというWritableストアを作成し、検索クエリを管理します。
  2. itemsストアの内容に基づいて、filteredItemsというDerivedストアを作成し、検索クエリと一致するアイテムだけを表示します。
  3. 検索ボックスに入力された内容に応じて、アイテムリストがリアルタイムで更新されるようにします。

期待される結果:

  • 検索ボックスに入力すると、それに応じたアイテムが表示されます。
<script>
    import { writable, derived } from 'svelte/store';

    const items = writable([
        { id: 1, name: 'Svelte Handbook' },
        { id: 2, name: 'JavaScript Guide' },
        { id: 3, name: 'CSS Tricks' },
        { id: 4, name: 'React Basics' }
    ]);

    const searchQuery = writable('');

    const filteredItems = derived(
        [items, searchQuery],
        ([$items, $searchQuery]) => {
            return $items.filter(item => item.name.toLowerCase().includes($searchQuery.toLowerCase()));
        }
    );
</script>

<input type="text" placeholder="検索..." bind:value={$searchQuery} />

<ul>
    {#each $filteredItems as item}
        <li>{item.name}</li>
    {/each}
</ul>

これらの演習問題を解くことで、Svelteストアを使った状態管理の実践力を高めることができます。各演習に取り組むことで、リアクティブなデータバインディングや状態管理の基本を理解し、さらに高度な状態管理の実装に自信を持つことができるようになります。次のセクションでは、これまで学んだことを簡潔にまとめます。

まとめ

本記事では、Svelteのストアを使った状態管理について、基本的な使い方から高度な応用例までを解説しました。Svelteのストアは、そのシンプルさと直感的なインターフェースにより、効率的な状態管理を実現します。Writable、Readable、Derivedストアを適切に使い分けることで、アプリケーションの状態を柔軟に管理できることが理解できたかと思います。

また、他の状態管理ライブラリとの比較を通じて、Svelteストアの利点や適用範囲を明確にし、実際にどのような状況で使用すべきかを示しました。さらに、演習問題を通じて、実践的なスキルを養い、Svelteのストアを活用した効果的な状態管理の実装方法を学ぶことができました。

Svelteストアの活用により、開発がシンプルで迅速になることを実感し、今後のプロジェクトでこの知識を応用していただければ幸いです。

コメント

コメントする

目次