【Svelte】$derived と $derived.by の使い分け

【Svelte】$derived と $derived.by の使い分け

$derivedは他の state から自動計算される値を作成します。元の state が変わると、自動的に再計算される。 $derived.byは複雑な計算ロジックが必要な場合に使用できる。

Svelte #Svelte

【Svelte】$derived と $derived.by の使い分け

サムネイル

$derivedは他の state から自動計算される値を作成します。元の state が変わると、自動的に再計算される。 $derived.byは複雑な計算ロジックが必要な場合に使用できる。

更新日: 9/12/2025

$derived - シンプルな計算

主に、一行で表現できる計算に使用します。

<script>
    let count = $state(0);
    let doubled = $derived(count * 2);
    let isEven = $derived(count % 2 === 0);
</script>

<p>カウント: {count}</p>
<p>2倍: {doubled}</p>
<p>偶数: {isEven ? 'はい' : 'いいえ'}</p>

いつ使う?

  • 数式計算:price * 1.1
  • 比較演算:score > 80
  • 文字列結合:firstName + ' ' + lastName
  • 単純な条件:age >= 18 ? '成人' : '未成年'

$derived.by - 複雑な計算

$derivedとの使い分けとして、複数行や複雑なロジックには $derived.by を使用します。

<script>
    let tasks = $state([
        { name: 'タスク1', done: false },
        { name: 'タスク2', done: true }
    ]);
    
    let progress = $derived.by(() => {
        const total = tasks.length;
        const completed = tasks.filter(t => t.done).length;
        const percentage = total > 0 ? (completed / total) * 100 : 0;
        
        return {
            total,
            completed,
            percentage: Math.round(percentage)
        };
    });
</script>

<p>進捗: {progress.completed}/{progress.total} ({progress.percentage}%)</p>

いつ使う?

  • 配列の集計処理
  • 複数の条件分岐
  • オブジェクトの変換
  • 複数ステップの計算

実用例での比較

ショッピングカート

<script>
    let items = $state([
        { name: '商品A', price: 100, qty: 2 },
        { name: '商品B', price: 200, qty: 1 }
    ]);
    
    // $derived - シンプルな計算
    let itemCount = $derived(items.length);
    
    // $derived.by - 複雑な計算
    let summary = $derived.by(() => {
        let subtotal = 0;
        let totalQty = 0;
        
        for (const item of items) {
            subtotal += item.price * item.qty;
            totalQty += item.qty;
        }
        
        const tax = subtotal * 0.1;
        const total = subtotal + tax;
        
        return {
            subtotal,
            tax: Math.round(tax),
            total: Math.round(total),
            totalQty
        };
    });
</script>

ユーザー表示名

<script>
    let user = $state({ firstName: '太郎', lastName: '山田', isVip: true });
    let settings = $state({ showFullName: true, showVipBadge: true });
    
    // $derived.by - 条件分岐が複雑
    let displayName = $derived.by(() => {
        let name = settings.showFullName 
            ? `${user.lastName} ${user.firstName}`
            : user.firstName;
            
        if (settings.showVipBadge && user.isVip) {
            name += ' ⭐VIP';
        }
        
        return name;
    });
</script>

更新タイミング

  • state変更時:関連するderived全てに変更通知
  • 表示時:実際に値を計算
<script>
    let count = $state(0);
    
    // countが0→1の時のみ更新(false→true)
    // 1→2の時は更新されない(true→true)
    let hasItems = $derived(count > 0);
</script>

<!-- hasItemsが変わった時だけテキスト更新 -->
<button>アイテム数: {hasItems ? 'あり' : 'なし'}</button>

derived値の一時的な変更

derived値は一時的に上書きできます(いいね機能など)

<script>
    let post = $state({ likes: 10 });
    let likes = $derived(post.likes);
    
    async function addLike() {
        likes += 1;  // 画面を即座に更新
        
        try {
            await api.like(post.id);
            post.likes = likes;  // サーバー処理成功
        } catch {
            likes -= 1;  // 失敗時に元に戻す
        }
    }
</script>

使い分け表

状況 使用
単純計算 $derived
文字列結合 $derived
配列処理 $derived.by
条件分岐多数 $derived.by
複数ステップ $derived.by

検索

検索条件に一致する記事が見つかりませんでした