こんにちは。よっしーです(^^)
今日は、SvelteKitでのstate管理について解説しています。
背景
SvelteKitでのstate管理について調査する機会がありましたので、その時の内容を備忘として記事に残しました。
SvelteKitでのstate管理について
クライアントのみのアプリの構築に慣れている場合、サーバーとクライアントにまたがるアプリでの状態(state)管理は困難に思えるかもしれません。このセクションでは、よくある落とし穴を回避するためのヒントを紹介します。
loadによる副作用なし
同じ理由で、あなたのload
関数は純粋であるべきです – 副作用はありません(おそらく時折のconsole.log(...)
を除いて)。例えば、コンポーネント内でストアの値を使用できるように、load
関数内でストアに書き込みたくなるかもしれません:
// +page.js
import { user } from '$lib/user';
/** @type {import('./$types').PageLoad} */
export async function load({ fetch }) {
const response = await fetch('/api/user');
// NEVER DO THIS!
user.set(await response.json());
}
前回の記事と同様に、これにより、1 人のユーザーの情報がすべてのユーザーが共有する場所に配置されます。代わりに、データを返すだけです…
コード解説
上記のコードは、SvelteKitアプリケーションのページロード関数を定義しています。以下が主な要素です:
import { user } from '$lib/user';
$lib/user
からuser
をインポートしています。これは恐らくSvelteのストアオブジェクトです。
/** @type {import('./$types').PageLoad} */
- これはTypeScriptの型注釈コメントです。
load
関数がSvelteKitのPageLoad
型に準拠していることを示しています。
export async function load({ fetch }) { ... }
- これはSvelteKitのページロード関数です。ページがロードされる際に実行されます。
fetch
パラメータは、SvelteKitが提供するフェッチ関数です。
const response = await fetch('/api/user');
/api/user
エンドポイントからデータを非同期で取得しています。
user.set(await response.json());
- レスポンスのJSONを解析し、その結果を
user
ストアにセットしています。 - しかし、コメント
// NEVER DO THIS!
(これは絶対にやるな!)が示すように、これは推奨されない方法です。
このコードの問題点:
- ページロード関数内でグローバルストアを直接更新することは、通常は避けるべきです。これはサーバーサイドレンダリング(SSR)時に問題を引き起こす可能性があります。
- 代わりに、
load
関数からデータを返し、コンポーネント内でストアを更新するか、別の方法でユーザー状態を管理することが推奨されます。
より適切なアプローチとしては、load
関数からデータを返し、それをページコンポーネントで使用することが考えられます。
改善コード
// +page.js
export async function load({ fetch }) {
const response = await fetch('/api/user');
return {
user: await response.json()
};
}
…そして、それを必要とするコンポーネントに渡すか、$page.data
を使用します。 もしサーバーサイドレンダリング(SSR)を使用していないなら、誤って他のユーザーのデータを公開してしまうリスクはありません。しかし、それでもload
関数内での副作用は避けるべきです – 副作用がないほうが、アプリケーションの動作を理解しやすくなります。
おわりに
今日は、 SvelteKitでのstate管理について解説しました。
何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント