こんにちは。よっしーです(^^)
今日は、SvelteKitでのstate管理について解説しています。
背景
SvelteKitでのstate管理について調査する機会がありましたので、その時の内容を備忘として記事に残しました。
SvelteKitでのstate管理について
クライアントのみのアプリの構築に慣れている場合、サーバーとクライアントにまたがるアプリでの状態(state)管理は困難に思えるかもしれません。このセクションでは、よくある落とし穴を回避するためのヒントを紹介します。
コンテキストに応じたストアの使用
$page.data
や他のアプリストアを使用できるのに、なぜ自分たちのストアは使用できないのか疑問に思うかもしれません。その答えは、サーバー上のアプリストアがSvelteのコンテキストAPIを使用しているからです – ストアはsetContext
を使用してコンポーネントツリーに関連付けられ、購読する際にはgetContext
で取得します。私たちも自分たちのストアで同じことができます:
// src/routes/+layout.svelte
<script>
import { setContext } from 'svelte';
import { writable } from 'svelte/store';
/** @type {import('./$types').LayoutData} */
export let data;
// Create a store and update it when necessary...
const user = writable();
$: user.set(data.user);
// ...and add it to the context for child components to access
setContext('user', user);
</script>
// src/routes/user/+page.svelte
<script>
import { getContext } from 'svelte';
// Retrieve user store from context
const user = getContext('user');
</script>
<p>Welcome {$user.name}</p>
解説
src/routes/+layout.svelte
:
<script>
import { setContext } from 'svelte';
import { writable } from 'svelte/store';
/** @type {import('./$types').LayoutData} */
export let data;
// Create a store and update it when necessary...
const user = writable();
$: user.set(data.user);
// ...and add it to the context for child components to access
setContext('user', user);
</script>
このコードは、アプリケーションのレイアウトコンポーネントを定義しています:
setContext
とwritable
をインポートしています。これらは Svelte の機能で、コンテキストの設定とストアの作成に使用されます。data
プロパティをエクスポートしています。これは SvelteKit のレイアウトデータを受け取ります。user
という名前の writable ストアを作成しています。- リアクティブステートメント
$: user.set(data.user)
を使用して、data.user
が変更されるたびにuser
ストアを更新します。 setContext('user', user)
を使用して、user
ストアをコンテキストに追加しています。これにより、子コンポーネントがこのストアにアクセスできるようになります。
src/routes/user/+page.svelte
:
<script>
import { getContext } from 'svelte';
// Retrieve user store from context
const user = getContext('user');
</script>
<p>Welcome {$user.name}</p>
このコードは、ユーザーページのコンポーネントを定義しています:
getContext
を Svelte からインポートしています。getContext('user')
を使用して、レイアウトコンポーネントで設定されたuser
ストアを取得しています。- テンプレート部分で、
$user.name
を使用してユーザー名を表示しています。$
記号は、ストアの値を直接参照するための Svelte の省略記法です。
このアプローチの利点:
- ユーザーデータをグローバルストアとして管理し、必要な箇所で簡単にアクセスできるようにしています。
- コンテキストを使用することで、props のバケツリレーを避け、深くネストされたコンポーネントでもユーザーデータにアクセスできます。
- リアクティブな更新により、
data.user
が変更されるたびにストアが自動的に更新されます。
このコードは、前回のコードの問題点を解決し、よりクリーンで管理しやすい方法でユーザーデータを扱っています。
サーバーサイドレンダリング(SSR)によってページがレンダリングされている間に、より深いレベルのページやコンポーネントでコンテキストベースのストアの値を更新しても、親コンポーネントの値には影響しません。これは、ストアの値が更新された時点で、すでに親コンポーネントがレンダリングされているためです。対照的に、クライアントサイド(CSRが有効な場合、これがデフォルトです)では、値は伝播され、階層の上位にあるコンポーネント、ページ、レイアウトが新しい値に反応します。したがって、ハイドレーション中の状態更新時に値が「フラッシュ」するのを避けるため、一般的には状態を上位から下位のコンポーネントに渡すことが推奨されます。
SSRを使用していない場合(そして将来的にSSRを使用する必要がないと保証できる場合)は、コンテキストAPIを使用せずに、共有モジュール内で安全に状態を保持することができます。
おわりに
今日は、 SvelteKitでのstate管理について解説しました。
何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント