1. 状態管理
Qwik フレームワークにおける状態管理に関して、具体的な例を用いて学びます。ここでは、シンプルな Todo リストアプリケーションを例に、状態の定義、更新、および状態を基にした UI のレンダリング方法を説明します。
Todo リストアプリケーション
目的
Todo リストアプリケーションを作成することで、Qwik における状態管理の概念を実際に体験します。ユーザーが新しいタスクを追加できる機能と、それらのタスクをリスト表示する機能を実装します。
実装ステップ
- Todo リストコンポーネントの作成:
TodoList
コンポーネントを定義し、タスクのリストを状態として保持します。- 新しいタスクを追加する機能を実装します。
- 状態の定義と更新:
useStore
フックを使用して、タスクリストの状態を管理します。- タスクを追加するアクションを定義し、そのアクションをフォームの送信イベントにバインドします。
- UI のレンダリング:
- 状態に基づいてタスクリストを動的にレンダリングします。
- 各タスクに対して、タスクの内容を表示する UI を定義します。
コード例
// src/components/TodoList.tsx
import { component$, useStore } from '@builder.io/qwik';
export const TodoList = component$(() => {
const state = useStore({
tasks: [],
newTask: '',
});
return (
<div>
<h2>Todo List</h2>
<form
onSubmit$={(event) => {
event.preventDefault();
state.tasks.push(state.newTask);
state.newTask = '';
}}
>
<input
type='text'
value={state.newTask}
onInput$={(event) => (state.newTask = event.target.value)}
/>
<button type='submit'>Add Task</button>
</form>
<ul>
{state.tasks.map((task) => (
<li>{task}</li>
))}
</ul>
</div>
);
});
2. グローバルな状態管理
Qwik フレームワークにおいて、サイト全体で参照および更新可能なグローバルな状態管理の概念と実践方法を学びます。具体的には、ユーザー認証状態(ログインしているかどうか)をアプリケーション全体で管理する例を通して説明します。
ユーザー認証状態の管理
目的
ユーザーがログインしているかどうかを追跡し、この情報をアプリケーション全体でアクセス可能にします。ログイン状態に基づいて、特定の UI コンポーネントを表示または非表示にする方法を示します。
実装ステップ
- グローバル状態の定義:
- アプリケーション全体で共有される状態(この場合はユーザーのログイン状態)を
useStore
フックを使って定義します。
- アプリケーション全体で共有される状態(この場合はユーザーのログイン状態)を
- 状態の更新と参照:
- ログインとログアウト機能を実装し、グローバル状態を更新します。
- 状態に基づいて条件付きで UI コンポーネントを表示します。
- UI のレンダリング:
- ログイン状態に基づいて、異なるコンポーネントやメッセージを表示します。
コード例
まず、グローバルな状態を管理するストアを定義します。
// src/store/userStore.ts
import { useStore } from '@builder.io/qwik';
export const useUserStore = () => {
const store = useStore({
isLoggedIn: false,
});
return store;
};
次に、ログイン機能を持つコンポーネントを作成します。
// src/components/LoginButton.tsx
import { component$ } from '@builder.io/qwik';
import { useUserStore } from '../store/userStore';
export const LoginButton = component$(() => {
const userStore = useUserStore();
return (
<button
onClick$={() => {
userStore.isLoggedIn = !userStore.isLoggedIn; // 簡単なトグルで実装
}}
>
{userStore.isLoggedIn ? 'Log Out' : 'Log In'}
</button>
);
});
最後に、ログイン状態に基づいて表示を変えるコンポーネントを実装します。
// src/components/UserGreeting.tsx
import { component$ } from '@builder.io/qwik';
import { useUserStore } from '../store/userStore';
export const UserGreeting = component$(() => {
const userStore = useUserStore();
return (
<div>
{userStore.isLoggedIn ? (
<h2>Welcome back, User!</h2>
) : (
<h2>Please log in.</h2>
)}
</div>
);
});
3. localStorage を使用した状態の永続化
Qwik フレームワークにおけるグローバルな状態管理では、ページリロード時に状態が初期化されてしまいます。これは、クライアントサイドの JavaScript で管理される状態が、新しいページリクエストでリセットされるためです。しかし、バックエンドのデータベースを使用せずに状態を永続化する方法があります。主な方法の一つは、Web Storage API(localStorage または sessionStorage)を利用することです。
localStorage
を使用すると、ブラウザが閉じられた後やページがリロードされた後もデータを保存できます。localStorage
はキーと値のペアでデータを保存し、そのデータは文字列形式でなければなりません。したがって、オブジェクトを保存する場合は、JSON.stringify
でシリアライズし、取り出す際にはJSON.parse
でデシリアライズする必要があります。
Qwik での具体的な実装例
以下は、Qwik フレームワークを使用して、ユーザーのログイン状態をlocalStorage
を使って永続化する例です。
ログイン状態の永続化
// src/components/LoginButton.tsx
import { component$, useStore } from '@builder.io/qwik';
export const LoginButton = component$(() => {
const state = useStore({
isLoggedIn: JSON.parse(localStorage.getItem('isLoggedIn') || 'false'),
});
const toggleLoginState = () => {
const newState = !state.isLoggedIn;
state.isLoggedIn = newState;
localStorage.setItem('isLoggedIn', JSON.stringify(newState));
};
return (
<button onClick$={toggleLoginState}>
{state.isLoggedIn ? 'Log Out' : 'Log In'}
</button>
);
});
このコンポーネントでは、useStore
を使ってisLoggedIn
状態を管理しています。localStorage
からこの状態を読み込むことで、ページリロード後もユーザーのログイン状態を維持できます。ボタンがクリックされると、toggleLoginState
関数が呼び出され、状態が反転し、新しい状態がlocalStorage
に保存されます。
注意点
localStorage
はクライアントサイドでのみアクセス可能です。サーバーサイドレンダリング(SSR)のコンテキストでは利用できませんので、クライアントサイドのコードでのみ使用してください。- セキュリティの観点から、機密情報は
localStorage
に保存しないようにしてください。localStorage
はクロスサイトスクリプティング(XSS)攻撃によって読み取られる可能性があります。
この方法により、バックエンドのデータベースを使わずに、Qwik フレームワークで管理している状態の永続化を実現できます。